diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index bf0b6ec..46fc8cc 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.24.x + go-version: 1.26.x - name: Get coverage tool run: | @@ -39,12 +39,33 @@ jobs: color: red namedLogo: checkmarx + - name: Vet + run: | + cd application/backend + go vet ./... + - name: Test run: | cd application/backend go test ./... -coverprofile cover.out go tool cover -func cover.out > covered.txt + - name: Test with the race detector + run: | + cd application/backend + go test -race ./... + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: 24.x + + - name: Frontend tests + run: | + cd application/frontend + npm ci + npm test + - name: Get coverage run: | cd application/backend @@ -75,3 +96,45 @@ jobs: message: ${{ env.COVERAGE }} color: green namedLogo: go + + release: + needs: build + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + concurrency: + group: release + cancel-in-progress: false + permissions: + contents: write + issues: write + pull-requests: write + steps: + # semantic-release derives the version from tags, so it needs all of them. + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - uses: docker/setup-qemu-action@v3 + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - uses: actions/setup-node@v4 + with: + node-version: 24.x + + # Plugins resolve from the repo, not the npx sandbox, so each is named here. + - name: Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: > + npx -y + -p semantic-release@25.0.9 + -p @semantic-release/commit-analyzer@13.0.1 + -p @semantic-release/release-notes-generator@14.1.1 + -p @semantic-release/exec@7.1.0 + -p @semantic-release/github@12.0.9 + -p conventional-changelog-conventionalcommits@10.2.1 + semantic-release diff --git a/.releaserc.json b/.releaserc.json new file mode 100644 index 0000000..47f0114 --- /dev/null +++ b/.releaserc.json @@ -0,0 +1,12 @@ +{ + "branches": ["main"], + "tagFormat": "${version}", + "plugins": [ + ["@semantic-release/commit-analyzer", { "preset": "conventionalcommits" }], + ["@semantic-release/release-notes-generator", { "preset": "conventionalcommits" }], + ["@semantic-release/exec", { + "prepareCmd": "docker buildx build --platform=linux/amd64,linux/arm64 --build-arg VERSION=${nextRelease.version} --tag devforth/onlogs:${nextRelease.version} --tag devforth/onlogs:latest --push ./application" + }], + ["@semantic-release/github", { "successComment": false, "failComment": false }] + ] +} diff --git a/README.md b/README.md index 8a3e459..75e2409 100644 --- a/README.md +++ b/README.md @@ -29,13 +29,13 @@ - πŸ”Ž Search through logs (configurable case sensitivity) - πŸ‘ View parameters (parsing JSON, showing local/UTC time for every logline) - πŸ”΄ Realtime logs updating +- πŸ—‚ Group services into named folders in the sidebar, per user +- πŸ“ˆ Prometheus metrics endpoint for log volume and OnLogs' own health ### Roadmap -- πŸ—‚ Grouping hosts - 🏷 Search and filter by tags (log status, time) - πŸ”ŒPlugins and internal ability to notify about some event (e.g. notify when Error happens) -- πŸ“Š Improved statistics ## Hello world & usage ### Docker Compose example with traefik @@ -47,6 +47,7 @@ - ADMIN_USERNAME=admin - ADMIN_PASSWORD= - PORT=8798 + - TRUSTED_PROXIES=172.16.0.0/12 # the docker network traefik reaches OnLogs over, see below # - ONLOGS_PATH_PREFIX=/onlogs if want to use with path prefix labels: @@ -66,7 +67,7 @@ volumes: ### Docker Run example with traefik ```sh -docker run --restart always -e ADMIN_USERNAME=admin -e PASSWORD= -e PORT=8798 \ +docker run --restart always -e ADMIN_USERNAME=admin -e ADMIN_PASSWORD= -e PORT=8798 \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ -v /var/lib/docker/containers:/var/lib/docker/containers \ -v /etc/hostname:/etc/hostname \ @@ -83,17 +84,107 @@ Once done, just go to and login as "admin" with . |----------------------------|---------------------------------|--------|-----------------| | DOCKER_HOST | URL of the docker socket to connect to. See below | `unix:///var/run/docker.sock` | | | ADMIN_USERNAME | Username for initial user | `admin` | if `AGENT=false` -| ADMIN_PASSWORD | Password for initial user | | if `AGENT=false` +| ADMIN_PASSWORD | Password for initial user. Must not be empty β€” OnLogs refuses to start without it unless `DISABLE_AUTH=true` | | if `AGENT=false` | PORT | Port to listen on | `2874` | if `AGENT=false` -| JWT_SECRET | Secret for JWT tokens for users | Generates randomly | - +| JWT_SECRET | Secret for JWT tokens for users. Generated with `crypto/rand` on first start and persisted to `leveldb/JWT_secret`. Set it explicitly if you want sessions to survive the volume being recreated | Generates randomly | - | ONLOGS_PATH_PREFIX | Base path if you using OnLogs not on subdomain | | only if using on path prefix -| AGENT | Toggles agent mode. If enabled, there will be no web interface available, and all logs will be sent and stored on HOST | `false` | - +| AGENT | Toggles agent mode. If enabled, there will be no web interface available, and all logs will be sent and stored on HOST. Parsed as a boolean, so `false`, `0` and an unset value all mean off | `false` | - | HOST | Url to OnLogs host from protocol to domain name. | | if `AGENT=true` | ONLOGS_TOKEN | Token that will use an agent to authorize and connect to HOST | Generates with OnLogs interface | if `AGENT=true` -| MAX_LOGS_SIZE | Maximum allowed total logs size before cleanup triggers. Accepts human-readable formats like 5GB, 500MB, 1.5GB etc. When exceeded, 10% of logs (by count) will be removed proportionally across containers starting from oldest | 10GB | - +| MAX_LOGS_SIZE | Maximum allowed total logs size before cleanup triggers. Accepts human-readable formats like 5GB, 500MB, 1.5GB etc. When exceeded, 10% of logs (by count) will be removed proportionally across containers starting from oldest. Validated at startup: an unparseable value stops OnLogs rather than silently disabling retention | 10GB | - | DISABLE_AUTH | Option to completely disable built in authentication in the application. When this option is set to `true` the app will behave like if the Administrator is logged in. The option to manage users will be removed. | false | - +| METRICS_TOKEN | Bearer token for the Prometheus endpoint at `/api/v1/metrics`. While it is unset the endpoint returns `401` and exposes nothing, so metrics are off by default. See [Metrics](#metrics) | | only for `/api/v1/metrics` +| TRUSTED_PROXIES | Peers allowed to name the client through `X-Forwarded-For` / `X-Real-IP`, as comma separated IPs and CIDR ranges. See [Behind a reverse proxy](#behind-a-reverse-proxy) | | only if behind nginx/traefik -### Docket socket URL +## Behind a reverse proxy + +Failed logins are rate limited per client address. Behind nginx or traefik every request +arrives from the proxy, so without `TRUSTED_PROXIES` all your users count as one client and +a single password sprayer locks out the rest. Set it to the addresses your proxy connects +from: + +``` +TRUSTED_PROXIES=172.16.0.0/12 # docker networks land here, so any containerised proxy does too +TRUSTED_PROXIES=127.0.0.1 # a proxy on the host +``` + +Keep the range as tight as your proxy allows β€” anything reaching OnLogs from a listed address +can call itself any client. + +Make sure the proxy actually sends the headers β€” traefik does by default, nginx needs +`proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;`. + +## Metrics + +Prometheus metrics at `${ONLOGS_PATH_PREFIX}/api/v1/metrics`. Set `METRICS_TOKEN` to enable +them β€” while it is unset every request gets a `401`, since the endpoint reveals container +names and log volumes. + +```yaml +scrape_configs: + - job_name: onlogs + metrics_path: /api/v1/metrics + authorization: + credentials: + static_configs: + - targets: ["onlogs:2874"] +``` + +| metric | labels | meaning | +|---|---|---| +| `onlogs_log_lines_total` | host, container, level | Log lines stored, by severity | +| `onlogs_stream_up` | host, container | 1 while a container's stream is attached | +| `onlogs_stream_cursor_timestamp_seconds` | host, container | Newest line ingested | +| `onlogs_dropped_replay_lines_total` | host, container | Lines dropped as replays | +| `onlogs_logs_size_bytes` / `_limit_bytes` | | Stored size, and `MAX_LOGS_SIZE` | +| `onlogs_container_db_size_bytes` | host, container | Stored size per container | +| `onlogs_retention_deleted_lines_total` | | Lines deleted by the quota | +| `onlogs_filesystem_size_bytes` / `_avail_bytes` | | The filesystem holding the logs | +| `onlogs_stats_workers`, `onlogs_websocket_connections` | | Workers and live viewers | +| `onlogs_goroutines`, `onlogs_heap_bytes` | | Process health | +| `onlogs_login_failures_total`, `onlogs_login_blocked_total` | | Rejected and blocked logins | +| `onlogs_build_info` | version | Always 1 | + +Alert on error rate, and on ingestion stalling while lines are still arriving: + +```yaml +- alert: OnLogsContainerErrors + expr: sum by (host, container) (rate(onlogs_log_lines_total{level="error"}[5m])) > 1 + for: 10m + +- alert: OnLogsIngestStalled + expr: | + (time() - onlogs_stream_cursor_timestamp_seconds > 300) + and on (host, container) (rate(onlogs_log_lines_total[10m]) > 0) + for: 5m +``` + +Worth knowing: `onlogs_stream_up` covers local containers only, not agent-forwarded ones; +size gauges refresh every 5 minutes and the limit is read once at startup; counters reset +on restart, as usual; and at most 1000 host/container pairs are counted. + +## Upgrading from 1.x + +Your logs are safe β€” nothing in the volume is migrated or deleted. + +**Check these three first, or the container will not start:** + +| Variable | What changed | +|---|---| +| `ADMIN_PASSWORD` | Must not be empty, unless `DISABLE_AUTH=true`. The 1.3.1 `docker run` example set `PASSWORD=` by mistake β€” if you copied it, fix the name. | +| `MAX_LOGS_SIZE` | Must be a valid size if you set it. Leaving it unset is fine. | +| `AGENT` | Now a real boolean. `AGENT=false` used to mean *on*, so you may have been running without a web interface by accident. `yes` and `on` no longer work. | + +**Everyone is logged out once.** 1.3.1 signed sessions with an empty key, which anyone +could forge. A real secret is generated on first start β€” set `JWT_SECRET` yourself if you +want sessions to survive the volume being recreated. + +Smaller changes: passwords are now hashed (rotate them if the database may have been +exposed); favourites are per user and need starring again; log levels are matched +case-insensitively, so charts change shape at the upgrade; live tailing needs your reverse +proxy to forward the original `Host` header. + +## Docker socket URL By default the app will connect using the raw unix socket. But this can be overriden via the ENV variable `DOCKER_HOST`. That way you can specify fully qualified URL to the socket or URL of an docker socket proxy. In `compose-socket-proxy.yml` you can see a sample compose file for starting the socket proxy. To use it in the app set `DOCKER_HOST=http://localhost:2375` in the ENV. diff --git a/application/Dockerfile b/application/Dockerfile index c5c57c2..7725ad5 100644 --- a/application/Dockerfile +++ b/application/Dockerfile @@ -1,9 +1,9 @@ -FROM node:16-alpine AS frontbuilder +FROM node:24-alpine AS frontbuilder WORKDIR /code/ ADD frontend/package-lock.json . ADD frontend/package.json . -RUN npm install -g npm:16 && npm ci +RUN npm ci ADD frontend/. . @@ -11,17 +11,15 @@ RUN npm run build COPY . /code/ -FROM alpine - -COPY --from=frontbuilder /code/dist/ /backend/dist/ +FROM golang:1.26-alpine AS backendbuilder -FROM golang:alpine AS backendbuilder +ARG VERSION=dev ADD backend/. /backend/ WORKDIR /backend/ RUN go mod download \ - && go build -o onlogs . + && go build -ldflags "-X github.com/devforth/OnLogs/app/metrics.Version=${VERSION}" -o onlogs . FROM alpine diff --git a/application/backend/app/agent/agent.go b/application/backend/app/agent/agent.go index fe2e2fe..809b22d 100644 --- a/application/backend/app/agent/agent.go +++ b/application/backend/app/agent/agent.go @@ -8,21 +8,29 @@ import ( "os" "github.com/devforth/OnLogs/app/util" - "github.com/devforth/OnLogs/app/vars" ) -func SendInitRequest(containers []string) { - postBody, _ := json.Marshal(map[string]interface{}{ +func post(path string, body map[string]any) (*http.Response, error) { + payload, _ := json.Marshal(body) + return http.Post(os.Getenv("HOST")+path, "application/json", bytes.NewBuffer(payload)) +} + +func identity() map[string]any { + return map[string]any{ "Hostname": util.GetHost(), "Token": os.Getenv("ONLOGS_TOKEN"), - "Services": containers, - }) - responseBody := bytes.NewBuffer(postBody) + } +} + +func SendInitRequest(containers []string) { + body := identity() + body["Services"] = containers - resp, err := http.Post(os.Getenv("HOST")+"/api/v1/addHost", "application/json", responseBody) + resp, err := post("/api/v1/addHost", body) if err != nil { panic("ERROR: Can't send request to host: " + err.Error()) } + defer resp.Body.Close() if resp.StatusCode != 200 { b, _ := io.ReadAll(resp.Body) @@ -31,15 +39,19 @@ func SendInitRequest(containers []string) { } func SendLogMessage(token string, container string, message_item []string) bool { - postBody, _ := json.Marshal(map[string]interface{}{ + resp, err := post("/api/v1/addLogLine", map[string]any{ "Host": util.GetHost(), "Token": token, "LogLine": []string{message_item[0], message_item[1]}, "Container": container, }) - resp, err := http.Post(os.Getenv("HOST")+"/api/v1/addLogLine", "application/json", bytes.NewBuffer(postBody)) + if err == nil { + defer resp.Body.Close() + } if err != nil || resp.StatusCode != 200 { - vars.BrokenLogs_DBs[container].Put([]byte(message_item[0]), []byte(message_item[1]), nil) + if buffer := util.GetDB(util.GetHost(), container, "brokenlogs"); buffer != nil { + buffer.Put([]byte(message_item[0]), []byte(message_item[1]), nil) + } return false } return true @@ -49,53 +61,49 @@ func TryResend() { token := os.Getenv("ONLOGS_TOKEN") containers, _ := os.ReadDir("leveldb/hosts/" + util.GetHost() + "/containers/") for _, container := range containers { - tmpDB := vars.BrokenLogs_DBs[container.Name()] - if tmpDB == nil { - tmpDB = util.GetDB(util.GetHost(), container.Name(), "/brokenLogs") - defer tmpDB.Close() + if !resendContainerBuffer(token, container.Name()) { + return } + } +} - iter := tmpDB.NewIterator(nil, nil) - defer iter.Release() - iter.First() - if iter.Value() == nil { - continue - } +// Returns false when the master is still unreachable, so the caller stops. +func resendContainerBuffer(token string, container string) bool { + buffer := util.GetDB(util.GetHost(), container, "brokenlogs") + if buffer == nil { + return true + } - if !SendLogMessage(token, container.Name(), []string{string(iter.Key()), string(iter.Value())}) { - return - } - tmpDB.Delete(iter.Key(), nil) + iter := buffer.NewIterator(nil, nil) + defer iter.Release() - for iter.Next() { - if !SendLogMessage(token, container.Name(), []string{string(iter.Key()), string(iter.Value())}) { - return - } - tmpDB.Delete(iter.Key(), nil) + for iter.Next() { + key := append([]byte{}, iter.Key()...) + value := append([]byte{}, iter.Value()...) + if !SendLogMessage(token, container, []string{string(key), string(value)}) { + return false } + buffer.Delete(key, nil) } + return true } func SendUpdate(containers []string) { - postBody, _ := json.Marshal(map[string]interface{}{ - "Hostname": util.GetHost(), - "Token": os.Getenv("ONLOGS_TOKEN"), - "Services": containers, - }) - responseBody := bytes.NewBuffer(postBody) + body := identity() + body["Services"] = containers - http.Post(os.Getenv("HOST")+"/api/v1/addHost", "application/json", responseBody) + if resp, err := post("/api/v1/addHost", body); err == nil { + resp.Body.Close() + } AskForDelete() } func AskForDelete() { - postBody, _ := json.Marshal(map[string]interface{}{ - "Hostname": util.GetHost(), - "Token": os.Getenv("ONLOGS_TOKEN"), - }) - responseBody := bytes.NewBuffer(postBody) - - resp, _ := http.Post(os.Getenv("HOST")+"/api/v1/askForDelete", "application/json", responseBody) + resp, err := post("/api/v1/askForDelete", identity()) + if err != nil { + return + } + defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) if string(body) != "" { diff --git a/application/backend/app/agent/resend_test.go b/application/backend/app/agent/resend_test.go new file mode 100644 index 0000000..ded1271 --- /dev/null +++ b/application/backend/app/agent/resend_test.go @@ -0,0 +1,75 @@ +package agent + +import ( + "net/http" + "net/http/httptest" + "os" + "testing" + + "github.com/devforth/OnLogs/app/util" +) + +func TestSendLogMessageBuffersInsteadOfPanicking(t *testing.T) { + t.Chdir(t.TempDir()) + os.Setenv("HOST", "http://127.0.0.1:1") + + container := "bufferedcontainer" + panicked := make(chan interface{}, 1) + go func() { + defer func() { panicked <- recover() }() + SendLogMessage("token", container, []string{"2026-02-10T12:56:09.230421754Z", "a line"}) + }() + if r := <-panicked; r != nil { + t.Fatalf("a failed delivery panicked instead of buffering: %v", r) + } + + buffer := util.GetDB(util.GetHost(), container, "brokenlogs") + if buffer == nil { + t.Fatal("no broken-logs buffer was opened") + } + value, err := buffer.Get([]byte("2026-02-10T12:56:09.230421754Z"), nil) + if err != nil { + t.Fatalf("the undelivered line was not buffered: %v", err) + } + if string(value) != "a line" { + t.Fatalf("buffered the wrong value: %q", value) + } +} + +func TestTryResendDeliversAndDrainsTheBuffer(t *testing.T) { + t.Chdir(t.TempDir()) + container := "resendcontainer" + + if err := os.MkdirAll("leveldb/hosts/"+util.GetHost()+"/containers/"+container, 0o700); err != nil { + t.Fatal(err) + } + + buffer := util.GetDB(util.GetHost(), container, "brokenlogs") + if buffer == nil { + t.Fatal("could not open the broken-logs buffer") + } + for _, ts := range []string{"2026-02-10T12:56:09.000000001Z", "2026-02-10T12:56:09.000000002Z"} { + if err := buffer.Put([]byte(ts), []byte("buffered "+ts), nil); err != nil { + t.Fatal(err) + } + } + + delivered := 0 + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + delivered++ + w.WriteHeader(http.StatusOK) + })) + defer server.Close() + os.Setenv("HOST", server.URL) + + TryResend() + + if delivered != 2 { + t.Fatalf("expected both buffered lines to be resent, got %d", delivered) + } + iter := buffer.NewIterator(nil, nil) + defer iter.Release() + if iter.Next() { + t.Fatalf("the buffer still holds %q after a successful resend", iter.Key()) + } +} diff --git a/application/backend/app/containerdb/classifier_test.go b/application/backend/app/containerdb/classifier_test.go new file mode 100644 index 0000000..946b683 --- /dev/null +++ b/application/backend/app/containerdb/classifier_test.go @@ -0,0 +1,36 @@ +package containerdb + +import "testing" + +// Shared with frontend/src/Views/Logs/classifier.test.mjs: both implementations +// must agree on every one of these. +var classifierCases = []struct { + line string + level string +}{ + {"ERROR something failed", "error"}, + {"Error: connection refused", "error"}, + {"error: connection refused", "error"}, + {"ERR disk full", "error"}, + {"WARN low memory", "warn"}, + {"WARNING low memory", "warn"}, + {"warning low memory", "warn"}, + {"DEBUG entering loop", "debug"}, + {"debug entering loop", "debug"}, + {"INFO started", "info"}, + {"INFO ERROR_COUNT=0", "info"}, + {"ONLOGS: Container listening started!", "meta"}, + {"plain application output", "other"}, + {"", "other"}, + {"\x1b[31mERROR\x1b[0m red text", "error"}, + {"the word information appears here", "info"}, + {"2026-02-10 INFO ready", "info"}, +} + +func TestGetLogStatusKeyMatchesTheSharedRules(t *testing.T) { + for _, c := range classifierCases { + if got := GetLogStatusKey(c.line); got != c.level { + t.Errorf("GetLogStatusKey(%q) = %q, want %q", c.line, got, c.level) + } + } +} diff --git a/application/backend/app/containerdb/containerdb.go b/application/backend/app/containerdb/containerdb.go index ef4243f..c1593b1 100644 --- a/application/backend/app/containerdb/containerdb.go +++ b/application/backend/app/containerdb/containerdb.go @@ -17,21 +17,79 @@ import ( leveldbUtil "github.com/syndtr/goleveldb/leveldb/util" ) +// One classification rule, mirrored by classifyLogLine in +// frontend/src/Views/Logs/functions.js. +var logLevels = []struct { + needle string + level string +}{ + {"ERROR", "error"}, + {"ERR", "error"}, + {"WARNING", "warn"}, + {"WARN", "warn"}, + {"DEBUG", "debug"}, + {"INFO", "info"}, + {"ONLOGS", "meta"}, +} + func GetLogStatusKey(message string) string { - if strings.Contains(message, "ERROR") || strings.Contains(message, "ERR") { - return "error" - } else if strings.Contains(message, "WARN") || strings.Contains(message, "WARNING") { - return "warn" - } else if strings.Contains(message, "DEBUG") { - return "debug" - } else if strings.Contains(message, "INFO") { - return "info" - } else if strings.Contains(message, "ONLOGS") { - return "meta" + for _, token := range strings.Fields(ansiEscapeRegex.ReplaceAllString(message, "")) { + upper := strings.ToUpper(token) + for _, level := range logLevels { + if strings.Contains(upper, level.needle) { + return level.level + } + } } return "other" } +func forEachContainer(visit func(host, container string)) error { + hosts, err := os.ReadDir("leveldb/hosts/") + if err != nil { + return fmt.Errorf("failed to read hosts directory: %v", err) + } + for _, h := range hosts { + containers, _ := os.ReadDir("leveldb/hosts/" + h.Name() + "/containers") + for _, c := range containers { + visit(h.Name(), c.Name()) + } + } + return nil +} + +// scanLimit 0 means scan every row. +func pruneUpTo(db *leveldb.DB, cutoff time.Time, scanLimit int) int { + batch := new(leveldb.Batch) + deleted := 0 + + iter := db.NewIterator(nil, nil) + scanned := 0 + for ok := iter.First(); ok && (scanLimit == 0 || scanned < scanLimit); ok = iter.Next() { + scanned++ + keyTime, err := time.Parse(time.RFC3339Nano, getDateTimeFromKey(string(iter.Key()))) + if err != nil { + fmt.Println("Error parsing key time:", err) + continue + } + if !keyTime.After(cutoff) { + batch.Delete(iter.Key()) + deleted++ + } + } + iter.Release() + + if deleted == 0 { + return 0 + } + if err := db.Write(batch, nil); err != nil { + fmt.Println("Failed to delete batch:", err) + return 0 + } + db.CompactRange(leveldbUtil.Range{Start: nil, Limit: nil}) + return deleted +} + func checkAndManageLogSize(host string, container string) error { maxSize, err := util.ParseHumanReadableSize(os.Getenv("MAX_LOGS_SIZE")) if err != nil { @@ -39,132 +97,63 @@ func checkAndManageLogSize(host string, container string) error { } for { - hosts, err := os.ReadDir("leveldb/hosts/") - if err != nil { - return fmt.Errorf("failed to read hosts directory: %v", err) - } - var totalSize int64 - for _, h := range hosts { - hostName := h.Name() - containers, _ := os.ReadDir("leveldb/hosts/" + hostName + "/containers") - for _, c := range containers { - containerName := c.Name() - size := util.GetDirSize(hostName, containerName) - totalSize += int64(size * 1024 * 1024) - } + if err := forEachContainer(func(h, c string) { + totalSize += int64(util.GetDirSize(h, c) * 1024 * 1024) + }); err != nil { + return err } - - // fmt.Printf("Max size: %d, current dir size: %d\n", maxSize, totalSize) if totalSize <= maxSize { - break + return nil } var cutoffKeys [][]byte - for _, h := range hosts { - hostName := h.Name() - containers, _ := os.ReadDir("leveldb/hosts/" + hostName + "/containers") - for _, c := range containers { - containerName := c.Name() - logsDB := util.GetDB(hostName, containerName, "logs") - if logsDB == nil { - continue - } - - cutoffKeysForContainer, err := getCutoffKeysForContainer(logsDB, 200) - if err != nil || len(cutoffKeysForContainer) == 0 { - continue - } - cutoffKeys = append(cutoffKeys, cutoffKeysForContainer) + if err := forEachContainer(func(h, c string) { + logsDB := util.GetDB(h, c, "logs") + if logsDB == nil { + return + } + if key, err := getCutoffKeysForContainer(logsDB, 200); err == nil && len(key) > 0 { + cutoffKeys = append(cutoffKeys, key) } + }); err != nil { + return err } if len(cutoffKeys) == 0 { fmt.Println("Nothing to delete, cutoff keys not found.") - break + return nil } - oldestCutoffKey := findOldestCutoffKey(cutoffKeys) - oldestTime, err := time.Parse(time.RFC3339Nano, getDateTimeFromKey(string(oldestCutoffKey))) + oldestTime, err := time.Parse(time.RFC3339Nano, getDateTimeFromKey(string(findOldestCutoffKey(cutoffKeys)))) if err != nil { fmt.Println("Error parsing oldest time:", err) - break + return nil } fmt.Println("Oldest time for deletion cutoff:", oldestTime) - for _, h := range hosts { - hostName := h.Name() - containers, _ := os.ReadDir("leveldb/hosts/" + hostName + "/containers") - for _, c := range containers { - containerName := c.Name() - logsDB := util.GetDB(hostName, containerName, "logs") - if logsDB == nil { + if err := forEachContainer(func(h, c string) { + // Everything the quota measures, or it can never come down. + for _, dbType := range util.PrunableDBs() { + db := util.GetDB(h, c, dbType) + if db == nil { continue } - - batch := new(leveldb.Batch) - deletedCount := 0 - iter := logsDB.NewIterator(nil, nil) - - count := 0 - for ok := iter.First(); ok && count < 200; ok = iter.Next() { - count++ - keyTime, err := time.Parse(time.RFC3339Nano, getDateTimeFromKey(string(iter.Key()))) - if err != nil { - fmt.Println("Error parsing key time:", err) - continue - } - if keyTime.Before(oldestTime) || keyTime.Equal(oldestTime) { - batch.Delete(iter.Key()) - deletedCount++ - } - } - iter.Release() - - if deletedCount > 0 { - err = logsDB.Write(batch, nil) - if err != nil { - fmt.Printf("Failed to delete batch in %s/%s: %v\n", hostName, containerName, err) - } else { - fmt.Printf("Deleted %d logs from %s/%s\n", deletedCount, hostName, containerName) - } - logsDB.CompactRange(leveldbUtil.Range{Start: nil, Limit: nil}) + scanLimit := 0 + if dbType == "logs" { + scanLimit = 200 } - - statusesDB := util.GetDB(hostName, containerName, "statuses") - if statusesDB != nil { - batch := new(leveldb.Batch) - deletedCountStatuses := 0 - iter := statusesDB.NewIterator(nil, nil) - - for ok := iter.First(); ok; ok = iter.Next() { - keyTime, err := time.Parse(time.RFC3339Nano, getDateTimeFromKey(string(iter.Key()))) - if err != nil { - fmt.Println("Error parsing key time:", err) - continue - } - if keyTime.Before(oldestTime) || keyTime.Equal(oldestTime) { - batch.Delete(iter.Key()) - deletedCountStatuses++ - } - } - iter.Release() - - if deletedCountStatuses > 0 { - err := statusesDB.Write(batch, nil) - if err != nil { - fmt.Printf("Failed to delete batch in statusesDB for %s/%s: %v\n", hostName, containerName, err) - } - statusesDB.CompactRange(leveldbUtil.Range{Start: nil, Limit: nil}) - } + if deleted := pruneUpTo(db, oldestTime, scanLimit); deleted > 0 && dbType == "logs" { + CountRetentionDeleted(deleted) + fmt.Printf("Deleted %d logs from %s/%s\n", deleted, h, c) } } + }); err != nil { + return err } time.Sleep(100 * time.Millisecond) } - - return nil } func getCutoffKeysForContainer(db *leveldb.DB, limit int) ([]byte, error) { @@ -206,6 +195,14 @@ func findOldestCutoffKey(cutoffKeys [][]byte) []byte { return oldestKey } +const ( + defaultLogsPerRequest = 30 + maxLogsPerRequest = 1000 +) + +// Bounds one scan. A var so tests can exercise the cap without a million rows. +var maxScanIterations = 1000000 + var ( logCleanupMu sync.Mutex nextCleanup time.Time @@ -247,7 +244,80 @@ func MaybeScheduleCleanup(host string, container string) { }() } +func NewStatCounter() map[string]uint64 { + return map[string]uint64{"error": 0, "debug": 0, "info": 0, "warn": 0, "meta": 0, "other": 0} +} + +// Bounded because a CI pipeline that mints a container name per release would +// otherwise grow this without limit. +const maxTrackedContainers = 1000 + +// Process-lifetime counts, unlike vars.Container_Stat_Counter which the +// statistics worker zeroes every minute. +var ( + logLineCounts = map[string]map[string]uint64{} + logLineCapReported bool +) + +func countLogStatus(location string, statusKey string) { + vars.Mutex.Lock() + defer vars.Mutex.Unlock() + + if vars.Container_Stat_Counter[location] == nil { + vars.Container_Stat_Counter[location] = NewStatCounter() + } + vars.Container_Stat_Counter[location][statusKey]++ + + total := logLineCounts[location] + if total == nil { + if len(logLineCounts) >= maxTrackedContainers { + if !logLineCapReported { + logLineCapReported = true + fmt.Printf("WARNING: tracking log line counts for %d containers; %s and later ones are not counted in /metrics\n", maxTrackedContainers, location) + } + return + } + total = NewStatCounter() + logLineCounts[location] = total + } + total[statusKey]++ +} + +var retentionDeleted atomic.Uint64 + +func CountRetentionDeleted(lines int) { + if lines > 0 { + retentionDeleted.Add(uint64(lines)) + } +} + +func RetentionDeletedLines() uint64 { + return retentionDeleted.Load() +} + +// LogLineCounts returns a deep copy: the live maps are written on every log line. +func LogLineCounts() map[string]map[string]uint64 { + vars.Mutex.Lock() + defer vars.Mutex.Unlock() + + snapshot := make(map[string]map[string]uint64, len(logLineCounts)) + for location, levels := range logLineCounts { + counts := make(map[string]uint64, len(levels)) + for level, value := range levels { + counts[level] = value + } + snapshot[location] = counts + } + return snapshot +} + func PutLogMessage(db *leveldb.DB, host string, container string, message_item []string) error { + if db == nil { + return fmt.Errorf("no database for %s/%s", host, container) + } + if len(message_item) < 2 { + return fmt.Errorf("malformed log line for %s/%s", host, container) + } if len(message_item[0]) < 30 { fmt.Println("WARNING: got broken timestamp: ", "timestamp: "+message_item[0], "message: "+message_item[1]) return nil @@ -262,45 +332,48 @@ func PutLogMessage(db *leveldb.DB, host string, container string, message_item [ location := host + "/" + container status_key := GetLogStatusKey(message_item[1]) logKey := buildLogKey(message_item[0]) - vars.Mutex.Lock() - if vars.Statuses_DBs[location] == nil { - vars.Statuses_DBs[location] = util.GetDB(host, container, "statuses") + + // Resolved before taking vars.Mutex: GetDB takes DBMutex and can panic, and + // it already caches the handle under that lock. + statusesDB := util.GetDB(host, container, "statuses") + + countLogStatus(location, status_key) + + if statusesDB != nil { + if err := statusesDB.Put([]byte(logKey), []byte(status_key), nil); err != nil { + // The handle may have been closed by a concurrent delete; without a + // retry the line is invisible to every severity filter, forever. + if reopened := util.GetDB(host, container, "statuses"); reopened != nil { + reopened.Put([]byte(logKey), []byte(status_key), nil) + } + } } - vars.Container_Stat_Counter[location][status_key]++ - vars.Statuses_DBs[location].Put([]byte(logKey), []byte(status_key), nil) - vars.Mutex.Unlock() err := db.Put([]byte(logKey), []byte(message_item[1]), nil) - tries := 0 - for err != nil && tries < 10 { - db = util.GetDB(host, container, "logs") - err = db.Put([]byte(logKey), []byte(message_item[1]), nil) + for tries := 0; err != nil && tries < 10; tries++ { time.Sleep(10 * time.Millisecond) - tries++ - } - if err != nil { - panic(err) + if reopened := util.GetDB(host, container, "logs"); reopened != nil { + db = reopened + err = db.Put([]byte(logKey), []byte(message_item[1]), nil) + } } return err } -func fitsForSearch(logLine string, message string, caseSensetivity bool) bool { - logLine = ansiEscapeRegex.ReplaceAllString(logLine, "") - message = ansiEscapeRegex.ReplaceAllString(message, "") - logLine = strings.Join(strings.Fields(logLine), " ") - message = strings.Join(strings.Fields(message), " ") - +func normalizeForSearch(s string, caseSensetivity bool) string { + s = ansiEscapeRegex.ReplaceAllString(s, "") + s = strings.Join(strings.Fields(s), " ") if !caseSensetivity { - logLine = strings.ToLower(logLine) - message = strings.ToLower(message) + s = strings.ToLower(s) } - - return strings.Contains(logLine, message) + return s } -func increaseAndMove(counter *int, move_direction func() bool) { - *counter++ - move_direction() +func fitsNormalizedSearch(logLine string, normalizedMessage string, caseSensetivity bool) bool { + if normalizedMessage == "" { + return true + } + return strings.Contains(normalizeForSearch(logLine, caseSensetivity), normalizedMessage) } func getMoveDirection(getPrev bool, iter iterator.Iterator) func() bool { @@ -310,15 +383,25 @@ func getMoveDirection(getPrev bool, iter iterator.Iterator) func() bool { return func() bool { return iter.Next() } } -func searchInit(iter iterator.Iterator, startWith string) bool { - iter.Last() - - if startWith != "" { - if !iter.Seek([]byte(startWith)) { - return startWith > getDateTimeFromKey(string(iter.Key())) +// Positions the iterator for the requested direction. A failed Seek means no key +// is >= startWith: walking newer there is genuinely finished, while walking older +// should start from the newest row. goleveldb leaves a failed Seek at dirEOI, +// where Prev() silently jumps to Last() β€” so the direction must be explicit. +func searchInit(iter iterator.Iterator, startWith string, getPrev bool) bool { + if startWith == "" { + if getPrev { + return iter.First() } + return iter.Last() } - return true + + if iter.Seek([]byte(startWith)) { + return true + } + if getPrev { + return false + } + return iter.Last() } func getDateTimeFromKey(key string) string { @@ -339,10 +422,20 @@ returns json obj like this: } */ func GetLogs(getPrev bool, include bool, host string, container string, message string, limit int, startWith string, caseSensetivity bool, status *string) map[string]interface{} { - logs_db := util.GetDB(host, container, "logs") + if limit <= 0 { + limit = defaultLogsPerRequest + } else if limit > maxLogsPerRequest { + limit = maxLogsPerRequest + } + + logs_db := util.GetDBIfExists(host, container, "logs") + if logs_db == nil { + return map[string]interface{}{"logs": [][]string{}, "last_processed_key": "", "is_end": true} + } + var statusDb *leveldb.DB if status != nil { - statusDb = util.GetDB(host, container, "statuses") + statusDb = util.GetDBIfExists(host, container, "statuses") } iter := logs_db.NewIterator(nil, nil) defer iter.Release() @@ -353,7 +446,7 @@ func GetLogs(getPrev bool, include bool, host string, container string, message logs := [][]string{} move_direction := getMoveDirection(getPrev, iter) - if !searchInit(iter, startWith) { + if !searchInit(iter, startWith, getPrev) { to_return["is_end"] = true return to_return } @@ -361,20 +454,32 @@ func GetLogs(getPrev bool, include bool, host string, container string, message counter := 0 iteration := 0 last_processed_key := "" - for counter < limit && iteration < 1000000 { + last_visited_key := "" + normalizedMessage := normalizeForSearch(message, caseSensetivity) + hitScanCap := false + for counter < limit { + if iteration >= maxScanIterations { + hitScanCap = true + break + } iteration += 1 key := iter.Key() if len(key) == 0 { to_return["is_end"] = true - increaseAndMove(&counter, move_direction) + counter++ + move_direction() continue } else { to_return["is_end"] = false } keyStr := string(key) + last_visited_key = keyStr timeStr := getDateTimeFromKey(keyStr) - if !include && (keyStr == startWith || timeStr == startWith) { + // Only the cursor row is skipped. Statistics cursors arrive without the + // " +-" suffix, which no full key can ever equal, so + // they are matched on that boundary instead. + if !include && (keyStr == startWith || strings.HasPrefix(keyStr, startWith+" +")) { move_direction() continue } @@ -388,22 +493,44 @@ func GetLogs(getPrev bool, include bool, host string, container string, message } } - if !fitsForSearch(value, message, caseSensetivity) { + if !fitsNormalizedSearch(value, normalizedMessage, caseSensetivity) { move_direction() continue } - logs = append(logs, []string{timeStr, value}) - increaseAndMove(&counter, move_direction) + logs = append(logs, []string{timeStr, value, keyStr}) + counter++ + move_direction() last_processed_key = keyStr } + if hitScanCap { + // Cut short rather than exhausted. is_end already reflects whether the + // iterator ran out, so only the cursor needs filling in: hand back the + // last key VISITED so the next request resumes past it. An empty cursor + // would restart the client at the newest row and loop forever. + to_return["scan_capped"] = true + if last_processed_key == "" { + last_processed_key = last_visited_key + } + } + to_return["logs"] = logs to_return["last_processed_key"] = last_processed_key return to_return } func DeleteContainer(host string, container string, fullDelete bool) { + // Both callers are bare goroutines, so this rejects rather than panics. + if !util.IsSafeName(host) || !util.IsSafeName(container) { + fmt.Println("ERROR: refusing to delete container with unsafe name:", host, container) + return + } + + for _, dbType := range []string{"logs", "statuses", "statistics", "streamstate"} { + util.ResetDB(host, container, dbType) + } + path := "leveldb/hosts/" + host + "/containers/" + container if fullDelete { os.RemoveAll(path) @@ -414,20 +541,13 @@ func DeleteContainer(host string, container string, fullDelete bool) { } } - if vars.ActiveDBs[container] != nil { - vars.ActiveDBs[container].Close() - vars.ActiveDBs[container] = util.GetDB(host, container, "active") - } - if vars.Statuses_DBs[host+"/"+container] != nil { - vars.Statuses_DBs[host+"/"+container].Close() - vars.Statuses_DBs[host+"/"+container] = util.GetDB(host, container, "statuses") - } - if vars.Stat_Containers_DBs[host+"/"+container] != nil { - vars.Stat_Containers_DBs[host+"/"+container].Close() - vars.Statuses_DBs[host+"/"+container] = util.GetDB(host, container, "statistics") + for _, dbType := range []string{"logs", "statuses", "statistics", "streamstate"} { + util.ResetDB(host, container, dbType) } vars.Mutex.Lock() - vars.Container_Stat_Counter[host+"/"+container] = map[string]uint64{"error": 0, "debug": 0, "info": 0, "warn": 0, "meta": 0, "other": 0} + vars.Container_Stat_Counter[host+"/"+container] = NewStatCounter() + // Dropped, not zeroed: frees a slot against maxTrackedContainers. + delete(logLineCounts, host+"/"+container) vars.Mutex.Unlock() } diff --git a/application/backend/app/containerdb/containerdb_test.go b/application/backend/app/containerdb/containerdb_test.go index b237598..8f925e6 100644 --- a/application/backend/app/containerdb/containerdb_test.go +++ b/application/backend/app/containerdb/containerdb_test.go @@ -20,16 +20,16 @@ func TestPutLogMessage(t *testing.T) { defer statusDB.Close() defer db.Close() - PutLogMessage(db, host, cont, []string{vars.Year + "-02-10T12:56:09.230421754Z", "vokAU6OdSulJGynsz wBaKssXuAPGk6ZFiQxq4sQHe7B9Q9RbTAy\r\n"}) - PutLogMessage(db, host, cont, []string{vars.Year + "-02-10T12:57:09.230421754Z", "ERROR wBaKssXuAPGk6ZFiQxq4sQHe7B9Q9RbTAy\r\n"}) - PutLogMessage(db, host, cont, []string{vars.Year + "-02-10T12:58:09.230421754Z", "WARN vokAU6OdSulJGynsz\r\n"}) - PutLogMessage(db, host, cont, []string{vars.Year + "-02-10T12:59:09.230421754Z", "DEBUG wBaKssXuAPGk6ZFiQxq4sQHe7B9Q9RbTAy\r\n"}) - PutLogMessage(db, host, cont, []string{vars.Year + "-02-10T12:59:59.230421754Z", "INFO fasdfasdfB&^*inuk\r\n"}) + PutLogMessage(db, host, cont, []string{testYear + "-02-10T12:56:09.230421754Z", "vokAU6OdSulJGynsz wBaKssXuAPGk6ZFiQxq4sQHe7B9Q9RbTAy\r\n"}) + PutLogMessage(db, host, cont, []string{testYear + "-02-10T12:57:09.230421754Z", "ERROR wBaKssXuAPGk6ZFiQxq4sQHe7B9Q9RbTAy\r\n"}) + PutLogMessage(db, host, cont, []string{testYear + "-02-10T12:58:09.230421754Z", "WARN vokAU6OdSulJGynsz\r\n"}) + PutLogMessage(db, host, cont, []string{testYear + "-02-10T12:59:09.230421754Z", "DEBUG wBaKssXuAPGk6ZFiQxq4sQHe7B9Q9RbTAy\r\n"}) + PutLogMessage(db, host, cont, []string{testYear + "-02-10T12:59:59.230421754Z", "INFO fasdfasdfB&^*inuk\r\n"}) keys := []string{ - vars.Year + "-02-10T12:56:09.230421754Z", vars.Year + "-02-10T12:57:09.230421754Z", - vars.Year + "-02-10T12:58:09.230421754Z", vars.Year + "-02-10T12:59:09.230421754Z", - vars.Year + "-02-10T12:59:59.230421754Z", + testYear + "-02-10T12:56:09.230421754Z", testYear + "-02-10T12:57:09.230421754Z", + testYear + "-02-10T12:58:09.230421754Z", testYear + "-02-10T12:59:09.230421754Z", + testYear + "-02-10T12:59:59.230421754Z", } for _, key := range keys { iter := db.NewIterator(nil, nil) @@ -58,7 +58,7 @@ func TestPutLogMessage(t *testing.T) { t.Error("Not expected error: ", r) } }() - PutLogMessage(db, "", cont, []string{vars.Year + "-02-10T12:57:09.230421754Z", "fasdf\r\n"}) + PutLogMessage(db, "", cont, []string{testYear + "-02-10T12:57:09.230421754Z", "fasdf\r\n"}) } func TestGetLogs(t *testing.T) { @@ -69,44 +69,60 @@ func TestGetLogs(t *testing.T) { vars.Statuses_DBs["Test/TestGetLogsCont"] = statusDB defer statusDB.Close() - PutLogMessage(db, "Test", "TestGetLogsCont", []string{vars.Year + "-02-10T12:57:09.230421754Z", "fasdf\r\n"}) - PutLogMessage(db, "Test", "TestGetLogsCont", []string{vars.Year + "-02-10T12:51:09.230421754Z", "fasdf\r\n"}) - PutLogMessage(db, "Test", "TestGetLogsCont", []string{vars.Year + "-02-10T12:52:09.230421754Z", "fasdf\r\n"}) - PutLogMessage(db, "Test", "TestGetLogsCont", []string{vars.Year + "-02-10T12:53:09.230421754Z", "fasdf\r\n"}) - PutLogMessage(db, "Test", "TestGetLogsCont", []string{vars.Year + "-02-10T12:54:09.230421754Z", "fasdf\r\n"}) + PutLogMessage(db, "Test", "TestGetLogsCont", []string{testYear + "-02-10T12:57:09.230421754Z", "fasdf\r\n"}) + PutLogMessage(db, "Test", "TestGetLogsCont", []string{testYear + "-02-10T12:51:09.230421754Z", "fasdf\r\n"}) + PutLogMessage(db, "Test", "TestGetLogsCont", []string{testYear + "-02-10T12:52:09.230421754Z", "fasdf\r\n"}) + PutLogMessage(db, "Test", "TestGetLogsCont", []string{testYear + "-02-10T12:53:09.230421754Z", "fasdf\r\n"}) + PutLogMessage(db, "Test", "TestGetLogsCont", []string{testYear + "-02-10T12:54:09.230421754Z", "fasdf\r\n"}) db.Close() var logs [][]string - logs = GetLogs(false, true, "Test", "TestGetLogsCont", "", 30, vars.Year+"-02-10T12:57:09.230421754Z", false, nil)["logs"].([][]string) + logs = GetLogs(false, true, "Test", "TestGetLogsCont", "", 30, testYear+"-02-10T12:57:09.230421754Z", false, nil)["logs"].([][]string) if len(logs) != 5 { t.Error("5 logItems must be returned!") } - if logs[0][0] != vars.Year+"-02-10T12:57:09.230421754Z" { + if logs[0][0] != testYear+"-02-10T12:57:09.230421754Z" { t.Error("Invalid first logItem datetime: ", logs[0][0]) } - if logs[4][0] != vars.Year+"-02-10T12:51:09.230421754Z" { + if logs[4][0] != testYear+"-02-10T12:51:09.230421754Z" { t.Error("Invalid last logItem datetime: ", logs[4][0]) } - logs = GetLogs(true, false, "Test", "TestGetLogsCont", "", 30, vars.Year+"-02-10T12:51:09.230421754Z", false, nil)["logs"].([][]string) + // Page with the cursor the API returns -- the full key -- which identifies + // exactly one row; a bare timestamp would drop every row sharing that instant. + oldest := GetLogs(true, false, "Test", "TestGetLogsCont", "", 1, "", false, nil) + oldestRows := oldest["logs"].([][]string) + if len(oldestRows) != 1 { + t.Fatalf("expected one row when paging forward from the start, got %d", len(oldestRows)) + } + if oldestRows[0][0] != testYear+"-02-10T12:51:09.230421754Z" { + t.Error("Invalid first logItem datetime: ", oldestRows[0][0]) + } + + cursor := oldest["last_processed_key"].(string) + if cursor == "" { + t.Fatal("GetLogs returned no cursor to page with") + } + + logs = GetLogs(true, false, "Test", "TestGetLogsCont", "", 30, cursor, false, nil)["logs"].([][]string) if len(logs) != 4 { t.Error("4 logItems must be returned!") } - if logs[0][0] != vars.Year+"-02-10T12:52:09.230421754Z" { + if logs[0][0] != testYear+"-02-10T12:52:09.230421754Z" { t.Error("Invalid first logItem datetime: ", logs[0][0]) } - if logs[3][0] != vars.Year+"-02-10T12:57:09.230421754Z" { + if logs[3][0] != testYear+"-02-10T12:57:09.230421754Z" { t.Error("Invalid last logItem datetime: ", logs[3][0]) } - logs = GetLogs(true, false, "Test", "TestGetLogsCont", "", 30, vars.Year+"-02-10T12:51:09.230421753Z", false, nil)["logs"].([][]string) + logs = GetLogs(true, false, "Test", "TestGetLogsCont", "", 30, testYear+"-02-10T12:51:09.230421753Z", false, nil)["logs"].([][]string) if len(logs) != 5 { t.Error("4 logItems must be returned!") } - if logs[0][0] != vars.Year+"-02-10T12:51:09.230421754Z" { + if logs[0][0] != testYear+"-02-10T12:51:09.230421754Z" { t.Error("Invalid first logItem datetime: ", logs[0][0]) } - if logs[4][0] != vars.Year+"-02-10T12:57:09.230421754Z" { + if logs[4][0] != testYear+"-02-10T12:57:09.230421754Z" { t.Error("Invalid last logItem datetime: ", logs[3][0]) } } @@ -138,7 +154,7 @@ func TestPutLogMessageSameTimestampAcrossRestart(t *testing.T) { statusDB, _ := leveldb.OpenFile("leveldb/hosts/"+host+"/containers/"+container+"/statuses", nil) vars.Statuses_DBs[location] = statusDB - ts := vars.Year + "-02-10T12:57:09.230421754Z" + ts := testYear + "-02-10T12:57:09.230421754Z" _ = PutLogMessage(db, host, container, []string{ts, "first"}) _ = PutLogMessage(db, host, container, []string{ts, "second"}) logKeyCounter.Store(0) diff --git a/application/backend/app/containerdb/cursor_test.go b/application/backend/app/containerdb/cursor_test.go new file mode 100644 index 0000000..590b80f --- /dev/null +++ b/application/backend/app/containerdb/cursor_test.go @@ -0,0 +1,135 @@ +package containerdb + +import ( + "os" + "testing" + + "github.com/devforth/OnLogs/app/vars" + "github.com/syndtr/goleveldb/leveldb" +) + +const sameMillisecond = "-02-10T12:44:03.560000000Z" + +func seedSameMillisecondRows(t *testing.T, host, container string) []string { + t.Helper() + _ = os.RemoveAll("leveldb/hosts/" + host) + t.Cleanup(func() { _ = os.RemoveAll("leveldb/hosts/" + host) }) + + vars.Mutex.Lock() + delete(vars.Container_Stat_Counter, host+"/"+container) + vars.Mutex.Unlock() + + db, err := leveldb.OpenFile("leveldb/hosts/"+host+"/containers/"+container+"/logs", nil) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + messages := []string{"first in the millisecond", "second in the millisecond", "third in the millisecond"} + for _, message := range messages { + if err := PutLogMessage(db, host, container, []string{testYear + sameMillisecond, message}); err != nil { + t.Fatal(err) + } + } + return messages +} + +func rowKey(row []string) string { + if len(row) < 3 { + return "" + } + return row[2] +} + +func pageEverything(t *testing.T, getPrev bool, host, container string, pageSize int) []string { + t.Helper() + + var seen []string + cursor := "" + for round := 0; round < 20; round++ { + result := GetLogs(getPrev, false, host, container, "", pageSize, cursor, false, nil) + rows := result["logs"].([][]string) + for _, row := range rows { + seen = append(seen, row[1]) + } + if len(rows) == 0 || result["is_end"] == true { + break + } + + next := result["last_processed_key"].(string) + if next == "" || next == cursor { + t.Fatalf("the cursor did not advance: %q", next) + } + cursor = next + } + return seen +} + +func assertEachExactlyOnce(t *testing.T, label string, seen []string, expected []string) { + t.Helper() + + counts := map[string]int{} + for _, message := range seen { + counts[message]++ + } + for _, message := range expected { + switch counts[message] { + case 0: + t.Errorf("%s: row %q was never returned", label, message) + case 1: + default: + t.Errorf("%s: row %q was returned %d times", label, message, counts[message]) + } + } + if len(seen) != len(expected) { + t.Errorf("%s: paged %d rows, expected %d: %v", label, len(seen), len(expected), seen) + } +} + +func TestSameMillisecondRowsPageExactlyOnceInBothDirections(t *testing.T) { + host, container := "CursorHost", "CursorContainer" + messages := seedSameMillisecondRows(t, host, container) + + // One row per page forces the cursor to land inside the millisecond group. + backwards := pageEverything(t, false, host, container, 1) + assertEachExactlyOnce(t, "newest-first", backwards, messages) + + forwards := pageEverything(t, true, host, container, 1) + assertEachExactlyOnce(t, "oldest-first", forwards, messages) +} + +func TestGetLogsReturnsAStableRowIdentity(t *testing.T) { + host, container := "IdentityHost", "IdentityContainer" + seedSameMillisecondRows(t, host, container) + + rows := GetLogs(false, false, host, container, "", 30, "", false, nil)["logs"].([][]string) + if len(rows) != 3 { + t.Fatalf("expected 3 rows, got %d", len(rows)) + } + + keys := map[string]struct{}{} + for _, row := range rows { + key := rowKey(row) + if key == "" { + t.Fatalf("row %v carries no stable key, so the client cannot deduplicate or page precisely", row) + } + if _, exists := keys[key]; exists { + t.Fatalf("two rows share the key %q", key) + } + keys[key] = struct{}{} + } +} + +func TestGetLogsWithAStaleFutureCursorReturnsNothing(t *testing.T) { + host, container := "StaleCursorHost", "StaleCursorContainer" + seedSameMillisecondRows(t, host, container) + + result := GetLogs(true, false, host, container, "", 30, "2999-01-01T00:00:00.000000000Z", false, nil) + rows := result["logs"].([][]string) + if len(rows) != 0 { + t.Fatalf("a cursor newer than every row returned %d rows; the iterator teleported back to the newest page: %v", len(rows), rows) + } + if result["is_end"] != true { + t.Errorf("expected is_end=true for an exhausted forward scan, got %v", result["is_end"]) + } +} diff --git a/application/backend/app/containerdb/delete_test.go b/application/backend/app/containerdb/delete_test.go new file mode 100644 index 0000000..9dca95a --- /dev/null +++ b/application/backend/app/containerdb/delete_test.go @@ -0,0 +1,46 @@ +package containerdb + +import ( + "os" + "testing" +) + +func TestDeleteContainerCannotRemoveATreeOutsideLeveldb(t *testing.T) { + t.Chdir(t.TempDir()) + + if err := os.MkdirAll("leveldb/hosts/realhost/containers", 0o700); err != nil { + t.Fatal(err) + } + if err := os.MkdirAll("victim_tree/nested", 0o700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile("victim_tree/nested/important", []byte("keep me"), 0o600); err != nil { + t.Fatal(err) + } + + DeleteContainer("realhost", "../../../../victim_tree", true) + + if _, err := os.Stat("victim_tree/nested/important"); err != nil { + t.Fatalf("an admin delete removed a tree outside leveldb/hosts: %v", err) + } +} + +func TestDeleteContainerLogsCannotEmptyATreeOutsideLeveldb(t *testing.T) { + t.Chdir(t.TempDir()) + + if err := os.MkdirAll("leveldb/hosts/realhost/containers", 0o700); err != nil { + t.Fatal(err) + } + if err := os.MkdirAll("victim_tree/nested", 0o700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile("victim_tree/nested/important", []byte("keep me"), 0o600); err != nil { + t.Fatal(err) + } + + DeleteContainer("realhost", "../../../../victim_tree", false) + + if _, err := os.Stat("victim_tree/nested/important"); err != nil { + t.Fatalf("a clear-logs request emptied a tree outside leveldb/hosts: %v", err) + } +} diff --git a/application/backend/app/containerdb/helpers_test.go b/application/backend/app/containerdb/helpers_test.go new file mode 100644 index 0000000..ee5956e --- /dev/null +++ b/application/backend/app/containerdb/helpers_test.go @@ -0,0 +1,12 @@ +package containerdb + +import ( + "strconv" + "time" +) + +var testYear = strconv.Itoa(time.Now().UTC().Year()) + +func fitsForSearch(logLine string, message string, caseSensetivity bool) bool { + return fitsNormalizedSearch(logLine, normalizeForSearch(message, caseSensetivity), caseSensetivity) +} diff --git a/application/backend/app/containerdb/limit_test.go b/application/backend/app/containerdb/limit_test.go new file mode 100644 index 0000000..7070134 --- /dev/null +++ b/application/backend/app/containerdb/limit_test.go @@ -0,0 +1,150 @@ +package containerdb + +import ( + "os" + "strconv" + "testing" + + "github.com/devforth/OnLogs/app/vars" + "github.com/syndtr/goleveldb/leveldb" +) + +func seedLogs(t *testing.T, host, container string, n int) { + t.Helper() + _ = os.RemoveAll("leveldb/hosts/" + host + "/containers/" + container) + vars.Container_Stat_Counter[host+"/"+container] = map[string]uint64{"error": 0, "debug": 0, "info": 0, "warn": 0, "meta": 0, "other": 0} + + db, err := leveldb.OpenFile("leveldb/hosts/"+host+"/containers/"+container+"/logs", nil) + if err != nil { + t.Fatal(err) + } + statusDB, err := leveldb.OpenFile("leveldb/hosts/"+host+"/containers/"+container+"/statuses", nil) + if err != nil { + t.Fatal(err) + } + vars.Statuses_DBs[host+"/"+container] = statusDB + + for i := 0; i < n; i++ { + ts := testYear + "-02-10T12:" + pad(i/60) + ":" + pad(i%60) + ".230421754Z" + if err := PutLogMessage(db, host, container, []string{ts, "line " + strconv.Itoa(i)}); err != nil { + t.Fatal(err) + } + } + db.Close() + statusDB.Close() + delete(vars.Statuses_DBs, host+"/"+container) +} + +func pad(v int) string { + s := strconv.Itoa(v) + if len(s) == 1 { + return "0" + s + } + return s +} + +func TestGetLogsAlwaysReportsIsEnd(t *testing.T) { + seedLogs(t, "LimitHost", "LimitCont", 5) + + for _, limit := range []int{-1, 0, 1, 5, 30} { + result := GetLogs(false, false, "LimitHost", "LimitCont", "", limit, "", false, nil) + if _, ok := result["is_end"]; !ok { + t.Errorf("limit=%d: response omits is_end, so the client cannot tell it has finished", limit) + } + } +} + +func TestGetLogsTreatsANonPositiveLimitAsADefaultPage(t *testing.T) { + seedLogs(t, "LimitHost", "LimitCont", 5) + + for _, limit := range []int{0, -1, -1000} { + logs := GetLogs(false, false, "LimitHost", "LimitCont", "", limit, "", false, nil)["logs"].([][]string) + if len(logs) != 5 { + t.Errorf("limit=%d returned %d rows, want all 5", limit, len(logs)) + } + } +} + +func TestGetLogsClampsAnEnormousLimit(t *testing.T) { + seedLogs(t, "ClampHost", "ClampCont", 1100) + + logs := GetLogs(false, false, "ClampHost", "ClampCont", "", 1<<30, "", false, nil)["logs"].([][]string) + if len(logs) > maxLogsPerRequest { + t.Fatalf("a caller-supplied limit of 2^30 returned %d rows; the response is unbounded", len(logs)) + } +} + +func TestGetLogsResumesPastTheScanCap(t *testing.T) { + seedLogs(t, "CapHost", "CapCont", 60) + + original := maxScanIterations + maxScanIterations = 10 + t.Cleanup(func() { maxScanIterations = original }) + + seen := map[string]int{} + cursor := "" + for round := 0; round < 40; round++ { + // "line 0" matches exactly one row, the OLDEST β€” far beyond the first cap + // window, since the scan walks newest-first. + result := GetLogs(false, false, "CapHost", "CapCont", "line 0", 30, cursor, false, nil) + + for _, row := range result["logs"].([][]string) { + seen[row[1]]++ + } + if result["is_end"] == true { + break + } + + next := result["last_processed_key"].(string) + if next == "" { + t.Fatalf("round %d: a capped scan returned no cursor, so the client restarts at the newest row", round) + } + if next == cursor { + t.Fatalf("round %d: the cursor did not advance past the cap (%q)", round, next) + } + cursor = next + } + + if len(seen) == 0 { + t.Fatal("a rare search term past the scan cap was never reachable") + } + for message, count := range seen { + if count != 1 { + t.Errorf("row %q was returned %d times across the capped scan", message, count) + } + } +} + +// GetDB opens-or-creates and caches forever, so an unknown container name must +// not reach it: each one would allocate a LevelDB tree and pin its descriptors. +func TestGetLogsDoesNotCreateADatabaseForAnUnknownContainer(t *testing.T) { + t.Chdir(t.TempDir()) + + if err := os.MkdirAll("leveldb/hosts/RealHost/containers/realcontainer", 0o700); err != nil { + t.Fatal(err) + } + + for i := 0; i < 5; i++ { + name := "no-such-container-" + strconv.Itoa(i) + result := GetLogs(false, false, "RealHost", name, "", 30, "", false, nil) + if rows := result["logs"].([][]string); len(rows) != 0 { + t.Fatalf("%s returned %d rows", name, len(rows)) + } + } + GetLogs(false, false, "NoSuchHostAtAll", "whatever", "", 30, "", false, nil) + + entries, err := os.ReadDir("leveldb/hosts/RealHost/containers") + if err != nil { + t.Fatal(err) + } + if len(entries) != 1 || entries[0].Name() != "realcontainer" { + names := []string{} + for _, e := range entries { + names = append(names, e.Name()) + } + t.Fatalf("reading unknown containers created databases: %v", names) + } + if _, err := os.Stat("leveldb/hosts/NoSuchHostAtAll"); err == nil { + t.Error("reading an unknown host created a host directory") + } +} diff --git a/application/backend/app/containerdb/loglinecount_test.go b/application/backend/app/containerdb/loglinecount_test.go new file mode 100644 index 0000000..e653824 --- /dev/null +++ b/application/backend/app/containerdb/loglinecount_test.go @@ -0,0 +1,90 @@ +package containerdb + +import ( + "os" + "strconv" + "testing" + + "github.com/devforth/OnLogs/app/vars" +) + +func resetLogLineCounts() { + vars.Mutex.Lock() + defer vars.Mutex.Unlock() + logLineCounts = map[string]map[string]uint64{} + logLineCapReported = false +} + +func TestLogLineCountsIsDeepCopy(t *testing.T) { + resetLogLineCounts() + defer resetLogLineCounts() + + countLogStatus("copy-host/copy-container", "error") + + snapshot := LogLineCounts() + snapshot["copy-host/copy-container"]["error"] = 99999 + + if got := LogLineCounts()["copy-host/copy-container"]["error"]; got != 1 { + t.Errorf("mutating the snapshot changed the source: got %d, want 1", got) + } +} + +// Every level from the first line, so rate() has no gap. +func TestLogLineCountsEmitsEveryLevel(t *testing.T) { + resetLogLineCounts() + defer resetLogLineCounts() + + countLogStatus("levels-host/levels-container", "error") + + counts := LogLineCounts()["levels-host/levels-container"] + for _, level := range []string{"error", "warn", "debug", "info", "meta", "other"} { + if _, ok := counts[level]; !ok { + t.Errorf("level %q missing from the snapshot", level) + } + } + if counts["info"] != 0 { + t.Errorf("unseen level info: got %d, want 0", counts["info"]) + } + if counts["error"] != 1 { + t.Errorf("seen level error: got %d, want 1", counts["error"]) + } +} + +func TestLogLineCountsCapsTrackedContainers(t *testing.T) { + resetLogLineCounts() + defer resetLogLineCounts() + + for i := 0; i < maxTrackedContainers+50; i++ { + countLogStatus("host/c"+strconv.Itoa(i), "error") + } + + if got := len(LogLineCounts()); got != maxTrackedContainers { + t.Errorf("tracked containers: got %d, want %d", got, maxTrackedContainers) + } + + // An already-tracked container keeps counting past the cap. + countLogStatus("host/c0", "error") + if got := LogLineCounts()["host/c0"]["error"]; got != 2 { + t.Errorf("tracked container stopped counting at the cap: got %d, want 2", got) + } +} + +func TestDeleteContainerDropsCounter(t *testing.T) { + const host, container = "drop-host", "drop-container" + location := host + "/" + container + defer os.RemoveAll("leveldb/hosts/" + host) + + resetLogLineCounts() + defer resetLogLineCounts() + + countLogStatus(location, "error") + if _, ok := LogLineCounts()[location]; !ok { + t.Fatal("counter missing before delete") + } + + DeleteContainer(host, container, true) + + if _, ok := LogLineCounts()[location]; ok { + t.Error("DeleteContainer left the counter in place; it must delete the key") + } +} diff --git a/application/backend/app/containerdb/mutex_test.go b/application/backend/app/containerdb/mutex_test.go new file mode 100644 index 0000000..43921e0 --- /dev/null +++ b/application/backend/app/containerdb/mutex_test.go @@ -0,0 +1,124 @@ +package containerdb + +import ( + "os" + "testing" + "time" + + "github.com/devforth/OnLogs/app/vars" + "github.com/syndtr/goleveldb/leveldb" +) + +func mutexIsFree(d time.Duration) bool { + acquired := make(chan struct{}) + go func() { + vars.Mutex.Lock() + vars.Mutex.Unlock() + close(acquired) + }() + select { + case <-acquired: + return true + case <-time.After(d): + return false + } +} + +func TestPutLogMessageHandlesAContainerWithNoStatCounterYet(t *testing.T) { + host := "FirstLineHost" + container := "FirstLineContainer" + location := host + "/" + container + _ = os.RemoveAll("leveldb/hosts/" + host + "/containers/" + container) + + vars.Mutex.Lock() + delete(vars.Container_Stat_Counter, location) + vars.Mutex.Unlock() + + db, err := leveldb.OpenFile("leveldb/hosts/"+host+"/containers/"+container+"/logs", nil) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + panicked := make(chan interface{}, 1) + go func() { + defer func() { panicked <- recover() }() + PutLogMessage(db, host, container, []string{testYear + "-02-10T12:56:09.230421754Z", "first line"}) + }() + + if r := <-panicked; r != nil { + t.Errorf("the first log line for a new container panicked: %v", r) + } + + if !mutexIsFree(3 * time.Second) { + t.Fatal("vars.Mutex was left locked, which freezes ingestion from every source host-wide") + } + + vars.Mutex.Lock() + counter := vars.Container_Stat_Counter[location] + vars.Mutex.Unlock() + if counter == nil { + t.Fatal("no stat counter was created for the container") + } + if counter["other"] != 1 { + t.Errorf("expected the line to be counted once, got %v", counter) + } +} + +func TestPutLogMessageCountsConcurrentlyWithoutRacing(t *testing.T) { + host := "ConcurrentHost" + container := "ConcurrentContainer" + _ = os.RemoveAll("leveldb/hosts/" + host + "/containers/" + container) + + vars.Mutex.Lock() + delete(vars.Container_Stat_Counter, host+"/"+container) + vars.Mutex.Unlock() + + db, err := leveldb.OpenFile("leveldb/hosts/"+host+"/containers/"+container+"/logs", nil) + if err != nil { + t.Fatal(err) + } + defer db.Close() + + const writers = 8 + done := make(chan error, writers) + for i := 0; i < writers; i++ { + go func() { + var failure error + defer func() { + if r := recover(); r != nil { + failure = errFromPanic(r) + } + done <- failure + }() + for n := 0; n < 25; n++ { + PutLogMessage(db, host, container, []string{testYear + "-02-10T12:56:09.230421754Z", "concurrent line"}) + } + }() + } + for i := 0; i < writers; i++ { + if err := <-done; err != nil { + t.Fatalf("concurrent ingestion panicked: %v", err) + } + } + + if !mutexIsFree(3 * time.Second) { + t.Fatal("vars.Mutex was left locked after concurrent ingestion") + } +} + +type panicError struct{ value interface{} } + +func (e panicError) Error() string { return "panic: " + toString(e.value) } + +func errFromPanic(r interface{}) error { return panicError{r} } + +func toString(v interface{}) string { + if s, ok := v.(string); ok { + return s + } + if e, ok := v.(error); ok { + return e.Error() + } + return "unknown" +} diff --git a/application/backend/app/containerdb/reset_test.go b/application/backend/app/containerdb/reset_test.go new file mode 100644 index 0000000..2b7e34b --- /dev/null +++ b/application/backend/app/containerdb/reset_test.go @@ -0,0 +1,88 @@ +package containerdb + +import ( + "os" + "testing" + + "github.com/devforth/OnLogs/app/util" + "github.com/devforth/OnLogs/app/vars" +) + +func TestDeleteContainerLeavesUsableHandlesBehind(t *testing.T) { + host, container := "ResetHost", "ResetContainer" + location := host + "/" + container + base := "leveldb/hosts/" + host + "/containers/" + container + _ = os.RemoveAll("leveldb/hosts/" + host) + t.Cleanup(func() { _ = os.RemoveAll("leveldb/hosts/" + host) }) + + // Warm the caches the way ingestion does. + logsDB := util.GetDB(host, container, "logs") + if logsDB == nil { + t.Fatal("could not open the logs database") + } + util.GetDB(host, container, "statuses") + util.GetDB(host, container, "statistics") + + if err := PutLogMessage(logsDB, host, container, []string{testYear + "-02-10T12:56:09.230421754Z", "before delete"}); err != nil { + t.Fatal(err) + } + + DeleteContainer(host, container, false) + + if _, err := os.Stat(base + "/active"); err == nil { + t.Error("DeleteContainer created a stray active/ directory; later log writes go there and are never read back") + } + + vars.DBMutex.RLock() + statuses := vars.Statuses_DBs[location] + stats := vars.Stat_Containers_DBs[location] + vars.DBMutex.RUnlock() + if statuses != nil && statuses == stats { + t.Error("the statistics database was stored in the statuses slot") + } + + reopened := util.GetDB(host, container, "logs") + if reopened == nil { + t.Fatal("the logs database could not be reopened after a delete") + } + if err := PutLogMessage(reopened, host, container, []string{testYear + "-02-10T12:57:09.230421754Z", "after delete"}); err != nil { + t.Fatalf("ingestion failed after a delete: %v", err) + } + + logs := GetLogs(false, false, host, container, "", 30, "", false, nil)["logs"].([][]string) + if len(logs) != 1 || logs[0][1] != "after delete" { + t.Fatalf("expected the post-delete line to be readable back, got %v", logs) + } +} + +func TestLogsOfSameNamedContainersOnDifferentHostsStaySeparate(t *testing.T) { + container := "sharedname" + for _, host := range []string{"HostAlpha", "HostBeta"} { + _ = os.RemoveAll("leveldb/hosts/" + host) + } + t.Cleanup(func() { + for _, host := range []string{"HostAlpha", "HostBeta"} { + _ = os.RemoveAll("leveldb/hosts/" + host) + } + }) + + for _, host := range []string{"HostAlpha", "HostBeta"} { + db := util.GetDB(host, container, "logs") + if db == nil { + t.Fatalf("could not open the logs database for %s", host) + } + if err := PutLogMessage(db, host, container, []string{testYear + "-02-10T12:56:09.230421754Z", "line from " + host}); err != nil { + t.Fatal(err) + } + } + + for _, host := range []string{"HostAlpha", "HostBeta"} { + logs := GetLogs(false, false, host, container, "", 30, "", false, nil)["logs"].([][]string) + if len(logs) != 1 { + t.Fatalf("%s: expected exactly its own line, got %d rows: %v", host, len(logs), logs) + } + if logs[0][1] != "line from "+host { + t.Fatalf("%s: read back another host's line: %q", host, logs[0][1]) + } + } +} diff --git a/application/backend/app/containerdb/retention_test.go b/application/backend/app/containerdb/retention_test.go new file mode 100644 index 0000000..33c3ff9 --- /dev/null +++ b/application/backend/app/containerdb/retention_test.go @@ -0,0 +1,69 @@ +package containerdb + +import ( + "os" + "testing" + + "github.com/devforth/OnLogs/app/util" + "github.com/devforth/OnLogs/app/vars" +) + +func TestRetentionMeasuresOnlyWhatItCanPrune(t *testing.T) { + host, container := "RetentionHost", "RetentionContainer" + base := "leveldb/hosts/" + host + "/containers/" + container + _ = os.RemoveAll("leveldb/hosts/" + host) + t.Cleanup(func() { _ = os.RemoveAll("leveldb/hosts/" + host) }) + + vars.Mutex.Lock() + delete(vars.Container_Stat_Counter, host+"/"+container) + vars.Mutex.Unlock() + + logsDB := util.GetDB(host, container, "logs") + if logsDB == nil { + t.Fatal("could not open the logs database") + } + for i := 0; i < 5; i++ { + ts := testYear + "-02-10T12:5" + string(rune('0'+i)) + ":09.230421754Z" + if err := PutLogMessage(logsDB, host, container, []string{ts, "a log line"}); err != nil { + t.Fatal(err) + } + } + + withLogsOnly := util.GetPrunableSize(host, container) + if withLogsOnly == 0 { + t.Fatal("prunable size is zero even though logs were written") + } + + // Something retention cannot delete from: a large broken-logs buffer. + if err := os.MkdirAll(base+"/brokenlogs", 0o700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(base+"/brokenlogs/ballast", make([]byte, 8*1024*1024), 0o600); err != nil { + t.Fatal(err) + } + + afterBallast := util.GetPrunableSize(host, container) + if afterBallast != withLogsOnly { + t.Errorf("a sub-database retention cannot prune changed the measured size: %v -> %v", + withLogsOnly, afterBallast) + } + + if util.GetDirSize(host, container) <= afterBallast { + t.Error("GetDirSize should still report the full directory, for the size display") + } +} + +func TestPrunableDBsCoverEverythingRetentionMeasures(t *testing.T) { + prunable := util.PrunableDBs() + for _, expected := range []string{"logs", "statuses", "statistics"} { + found := false + for _, actual := range prunable { + if actual == expected { + found = true + } + } + if !found { + t.Errorf("%q is measured by retention but never pruned", expected) + } + } +} diff --git a/application/backend/app/daemon/daemon.go b/application/backend/app/daemon/daemon.go index c1c7aba..00b9ea4 100644 --- a/application/backend/app/daemon/daemon.go +++ b/application/backend/app/daemon/daemon.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io" + "maps" "os" "strconv" "strings" @@ -20,7 +21,9 @@ import ( "github.com/devforth/OnLogs/app/vars" "github.com/docker/docker/api/types/container" "github.com/docker/docker/pkg/stdcopy" + "github.com/gorilla/websocket" "github.com/syndtr/goleveldb/leveldb" + leveldbUtil "github.com/syndtr/goleveldb/leveldb/util" ) const ( @@ -40,24 +43,35 @@ type DaemonService struct { streamSeq uint64 recentFingerprints map[string][]string recentSet map[string]map[string]struct{} -} + droppedReplays map[string]int -func (h *DaemonService) ensureRuntimeState() { - h.streamsMu.Lock() - defer h.streamsMu.Unlock() + // droppedReplays is cleared when a stream ends; these two are for /metrics, + // which needs a total that survives a restart and a cursor readable without + // touching LevelDB. + droppedReplayTotals map[string]uint64 + cursorTimestamps map[string]time.Time +} - if h.streamCancels == nil { - h.streamCancels = map[string]context.CancelFunc{} - } - if h.streamIDs == nil { - h.streamIDs = map[string]uint64{} +func NewDaemonService(dockerClient *docker.DockerService) *DaemonService { + return &DaemonService{ + DockerClient: dockerClient, + streamCancels: map[string]context.CancelFunc{}, + streamIDs: map[string]uint64{}, + recentFingerprints: map[string][]string{}, + recentSet: map[string]map[string]struct{}{}, + droppedReplays: map[string]int{}, + droppedReplayTotals: map[string]uint64{}, + cursorTimestamps: map[string]time.Time{}, } - if h.recentFingerprints == nil { - h.recentFingerprints = map[string][]string{} - } - if h.recentSet == nil { - h.recentSet = map[string]map[string]struct{}{} +} + +func noteMeta(db *leveldb.DB, host, containerName, token string, toHost bool, message string) { + if toHost { + agent.SendLogMessage(token, containerName, + strings.SplitN(createLogMessage(nil, host, containerName, message), " ", 2)) + return } + createLogMessage(db, host, containerName, message) } func createLogMessage(db *leveldb.DB, host string, container string, message string) string { @@ -68,27 +82,6 @@ func createLogMessage(db *leveldb.DB, host string, container string, message str return datetime + " " + message } -func validateMessage(message string) (string, bool) { - for !strings.HasPrefix(message, vars.Year) { - message = message[1:] - if len(message) < 31 { - return "", false - } - } - - return message, true -} - -func closeActiveStream(containerName string) { - newDaemonStreams := make([]string, 0, len(vars.Active_Daemon_Streams)) - for _, stream := range vars.Active_Daemon_Streams { - if stream != containerName { - newDaemonStreams = append(newDaemonStreams, stream) - } - } - vars.Active_Daemon_Streams = newDaemonStreams -} - func normalizeTimestamp(raw string) (string, time.Time, error) { ts, err := time.Parse(time.RFC3339Nano, strings.TrimSpace(raw)) if err != nil { @@ -112,15 +105,12 @@ func parseDockerLogLine(line string) ([]string, time.Time, bool) { return []string{tsStr, parts[1]}, ts, true } -func (h *DaemonService) isRecentDuplicate(containerName, fingerprint string) bool { - h.streamsMu.Lock() - defer h.streamsMu.Unlock() - +func (h *DaemonService) rememberFingerprint(containerName, fingerprint string) { if h.recentSet[containerName] == nil { h.recentSet[containerName] = map[string]struct{}{} } if _, exists := h.recentSet[containerName][fingerprint]; exists { - return true + return } h.recentSet[containerName][fingerprint] = struct{}{} @@ -130,12 +120,141 @@ func (h *DaemonService) isRecentDuplicate(containerName, fingerprint string) boo h.recentFingerprints[containerName] = h.recentFingerprints[containerName][1:] delete(h.recentSet[containerName], toDrop) } +} +// seedBoundaryFingerprints loads the lines already stored at exactly the cursor +// timestamp, so a replay of them is recognised while a genuinely new line +// sharing that nanosecond is still kept. +func (h *DaemonService) seedBoundaryFingerprints(host, containerName string, cursor time.Time) { + if cursor.IsZero() { + return + } + db := util.GetDB(host, containerName, "logs") + if db == nil { + return + } + + prefix := cursor.UTC().Format(streamTimestampFmt) + iter := db.NewIterator(leveldbUtil.BytesPrefix([]byte(prefix)), nil) + defer iter.Release() + + h.streamsMu.Lock() + defer h.streamsMu.Unlock() + for iter.Next() { + h.rememberFingerprint(containerName, prefix+" "+string(iter.Value())) + } +} + +func (h *DaemonService) countDroppedReplay(containerName string) { + + h.streamsMu.Lock() + defer h.streamsMu.Unlock() + h.droppedReplays[containerName]++ + h.droppedReplayTotals[util.GetHost()+"/"+containerName]++ + if count := h.droppedReplays[containerName]; count == 1 || count%100 == 0 { + fmt.Printf("INFO: dropped %d replayed log line(s) for %s\n", count, containerName) + } +} + +func (h *DaemonService) DroppedReplays(containerName string) int { + h.streamsMu.Lock() + defer h.streamsMu.Unlock() + return h.droppedReplays[containerName] +} + +// Keyed host/container, and survives a stream restart so the counter does not +// reset every time a container bounces. +func (h *DaemonService) DroppedReplayTotals() map[string]uint64 { + h.streamsMu.Lock() + defer h.streamsMu.Unlock() + return maps.Clone(h.droppedReplayTotals) +} + +// Mirrors what saveCursor persisted, so a scrape needs no LevelDB. +func (h *DaemonService) CursorTimestamps() map[string]time.Time { + h.streamsMu.Lock() + defer h.streamsMu.Unlock() + return maps.Clone(h.cursorTimestamps) +} + +func (h *DaemonService) isRecentDuplicate(containerName, fingerprint string) bool { + h.streamsMu.Lock() + defer h.streamsMu.Unlock() + + if h.recentSet[containerName] == nil { + h.recentSet[containerName] = map[string]struct{}{} + } + if _, exists := h.recentSet[containerName][fingerprint]; exists { + return true + } + + h.rememberFingerprint(containerName, fingerprint) return false } +// storedThrough is the cursor as persisted: the timestamp of the newest line +// already stored. getResumeSince deliberately rewinds behind it, so everything +// the stream replays up to this point is already on disk. +func (h *DaemonService) storedThrough(host, containerName string) time.Time { + db := util.GetDB(host, containerName, "streamstate") + if db == nil { + return time.Time{} + } + raw, err := db.Get([]byte(cursorKey), nil) + if err != nil || len(raw) == 0 { + return time.Time{} + } + ts, err := time.Parse(time.RFC3339Nano, string(raw)) + if err != nil { + return time.Time{} + } + return ts +} + +// ingestLine stores one streamed line, dropping anything the previous run had +// already persisted. Returns true when the line was stored. +func (h *DaemonService) ingestLine(host, containerName string, currentDB *leveldb.DB, token string, toHost bool, storedThrough time.Time, line string) bool { + + logItem, cursorTS, ok := parseDockerLogLine(line) + if !ok { + return false + } + + // Docker's Since is floored to whole seconds and the cursor is rewound on + // purpose, so every attach replays lines that are already stored. + if !storedThrough.IsZero() && cursorTS.Before(storedThrough) { + h.countDroppedReplay(containerName) + return false + } + + fingerprint := logItem[0] + " " + logItem[1] + if h.isRecentDuplicate(containerName, fingerprint) { + h.countDroppedReplay(containerName) + return false + } + + if toHost { + agent.SendLogMessage(token, containerName, logItem) + h.saveCursor(host, containerName, cursorTS) + return true + } + + if err := containerdb.PutLogMessage(currentDB, host, containerName, logItem); err != nil { + fmt.Println("ERROR:", err.Error()) + return false + } + h.saveCursor(host, containerName, cursorTS) + + toSend, _ := json.Marshal(logItem) + vars.Broadcast(containerName, websocket.TextMessage, toSend) + return true +} + func (h *DaemonService) getResumeSince(host, containerName string) time.Time { db := util.GetDB(host, containerName, "streamstate") + if db == nil { + return time.Now().Add(-initialBackfill) + } raw, err := db.Get([]byte(cursorKey), nil) if err != nil || len(raw) == 0 { return time.Now().Add(-initialBackfill) @@ -150,7 +269,15 @@ func (h *DaemonService) getResumeSince(host, containerName string) time.Time { } func (h *DaemonService) saveCursor(host, containerName string, ts time.Time) { + + h.streamsMu.Lock() + h.cursorTimestamps[host+"/"+containerName] = ts.UTC() + h.streamsMu.Unlock() + db := util.GetDB(host, containerName, "streamstate") + if db == nil { + return + } err := db.Put([]byte(cursorKey), []byte(ts.UTC().Format(streamTimestampFmt)), nil) if err != nil { fmt.Println("ERROR: unable to save stream cursor:", err) @@ -190,12 +317,22 @@ func (h *DaemonService) streamDockerLogs(ctx context.Context, rc io.ReadCloser, _ = pw.CloseWithError(err) }() - if scanErr := scanLogs(ctx, pr, onLine); scanErr != nil { - return scanErr - } + scanErr := scanLogs(ctx, pr, onLine) + + // Release the writer before waiting on it. StdCopy may be parked in + // pw.Write, and neither closing rc nor cancelling ctx unblocks a blocked + // write -- so without this, an early return from scanLogs (cancellation, or + // a line over the scanner's 1 MiB limit) leaves StdCopy stuck, this function + // never returns, finalizeStream never runs, and EnsureStream refuses to + // restart that container for the life of the process. + _ = pr.CloseWithError(io.ErrClosedPipe) copyErr := <-copyDone - if copyErr != nil && !errors.Is(copyErr, io.EOF) && !errors.Is(copyErr, context.Canceled) { + if scanErr != nil { + return scanErr + } + if copyErr != nil && !errors.Is(copyErr, io.EOF) && !errors.Is(copyErr, context.Canceled) && + !errors.Is(copyErr, io.ErrClosedPipe) { return copyErr } return nil @@ -222,13 +359,26 @@ func (h *DaemonService) finalizeStream(containerName string, streamID uint64) bo return false } + // Dropping the CancelFunc without calling it leaks streamCtx and the + // watchdog goroutine parked on <-ctx.Done() for every stream that ends. + if cancel, ok := h.streamCancels[containerName]; ok { + defer cancel() + } delete(h.streamCancels, containerName) delete(h.streamIDs, containerName) + delete(h.recentSet, containerName) + delete(h.recentFingerprints, containerName) + delete(h.droppedReplays, containerName) + // droppedReplayTotals deliberately survives; the cursor does not, since a + // stopped stream has no progress to fall behind on. + delete(h.cursorTimestamps, util.GetHost()+"/"+containerName) return true } func (h *DaemonService) runContainerStream(ctx context.Context, containerName string, toHost bool, streamID uint64) { host := util.GetHost() + storedThrough := h.storedThrough(host, containerName) + h.seedBoundaryFingerprints(host, containerName, storedThrough) since := h.getResumeSince(host, containerName) rc, err := h.DockerClient.Client.ContainerLogs( ctx, @@ -244,7 +394,7 @@ func (h *DaemonService) runContainerStream(ctx context.Context, containerName st if err != nil { fmt.Println("ERROR: unable to attach logs stream for", containerName, ":", err) if h.finalizeStream(containerName, streamID) { - closeActiveStream(containerName) + vars.RemoveActiveStream(containerName) } return } @@ -257,63 +407,26 @@ func (h *DaemonService) runContainerStream(ctx context.Context, containerName st currentDB := util.GetDB(host, containerName, "logs") token := os.Getenv("ONLOGS_TOKEN") - if toHost { - agent.SendLogMessage(token, containerName, strings.SplitN(createLogMessage(nil, host, containerName, "ONLOGS: Container listening started!"), " ", 2)) - } else { - createLogMessage(currentDB, host, containerName, "ONLOGS: Container listening started!") - } + noteMeta(currentDB, host, containerName, token, toHost, "ONLOGS: Container listening started!") streamErr := h.streamDockerLogs(ctx, rc, func(line string) { - logItem, cursorTS, ok := parseDockerLogLine(line) - if !ok { - return - } - - fingerprint := logItem[0] + " " + logItem[1] - if h.isRecentDuplicate(containerName, fingerprint) { - return - } - - if toHost { - agent.SendLogMessage(token, containerName, logItem) - h.saveCursor(host, containerName, cursorTS) - return - } - - err := containerdb.PutLogMessage(currentDB, host, containerName, logItem) - if err != nil { - fmt.Println("ERROR:", err.Error()) - return - } - h.saveCursor(host, containerName, cursorTS) - - toSend, _ := json.Marshal(logItem) - for _, c := range vars.Connections[containerName] { - c.WriteMessage(1, toSend) - } + h.ingestLine(host, containerName, currentDB, token, toHost, storedThrough, line) }, !h.isContainerTTY(ctx, containerName)) - if streamErr != nil && ctx.Err() == nil { - if toHost { - agent.SendLogMessage(token, containerName, strings.SplitN(createLogMessage(nil, host, containerName, "ONLOGS: Container listening stopped! ("+streamErr.Error()+")"), " ", 2)) - } else { - createLogMessage(currentDB, host, containerName, "ONLOGS: Container listening stopped! ("+streamErr.Error()+")") - } - } else if ctx.Err() == nil { - if toHost { - agent.SendLogMessage(token, containerName, strings.SplitN(createLogMessage(nil, host, containerName, "ONLOGS: Container listening stopped! (EOF)"), " ", 2)) - } else { - createLogMessage(currentDB, host, containerName, "ONLOGS: Container listening stopped! (EOF)") + if ctx.Err() == nil { + reason := "(EOF)" + if streamErr != nil { + reason = "(" + streamErr.Error() + ")" } + noteMeta(currentDB, host, containerName, token, toHost, "ONLOGS: Container listening stopped! "+reason) } if h.finalizeStream(containerName, streamID) { - closeActiveStream(containerName) + vars.RemoveActiveStream(containerName) } } func (h *DaemonService) EnsureStream(ctx context.Context, containerName string) { - h.ensureRuntimeState() h.streamsMu.Lock() if _, exists := h.streamCancels[containerName]; exists { @@ -327,11 +440,9 @@ func (h *DaemonService) EnsureStream(ctx context.Context, containerName string) h.streamIDs[containerName] = streamID h.streamsMu.Unlock() - if !util.Contains(containerName, vars.Active_Daemon_Streams) { - vars.Active_Daemon_Streams = append(vars.Active_Daemon_Streams, containerName) - } + vars.AddActiveStream(containerName) - if os.Getenv("AGENT") != "" { + if util.IsAgentMode() { go h.runContainerStream(streamCtx, containerName, true, streamID) return } @@ -339,7 +450,6 @@ func (h *DaemonService) EnsureStream(ctx context.Context, containerName string) } func (h *DaemonService) StopStream(containerName string) { - h.ensureRuntimeState() h.streamsMu.Lock() cancel, exists := h.streamCancels[containerName] @@ -352,15 +462,19 @@ func (h *DaemonService) StopStream(containerName string) { if exists { cancel() } - closeActiveStream(containerName) + vars.RemoveActiveStream(containerName) } -func (h *DaemonService) CreateDaemonToHostStream(ctx context.Context, containerName string) { - h.runContainerStream(ctx, containerName, true, 0) -} - -func (h *DaemonService) CreateDaemonToDBStream(ctx context.Context, containerName string) { - h.runContainerStream(ctx, containerName, false, 0) +// runningNames keeps only containers docker reports as running. Attaching to an +// exited container writes a started/stopped META pair on every reconcile. +func runningNames(result []docker.ContainerNamesResult) []string { + var names []string + for i := range result { + if result[i].Running && result[i].Name != "" { + names = append(names, result[i].Name) + } + } + return names } // returns list of names of docker containers from docker daemon @@ -368,37 +482,25 @@ func (h *DaemonService) GetContainersList(ctx context.Context) []string { result, err := h.DockerClient.GetContainerNames(ctx) if err != nil { fmt.Println("ERROR: failed to get containers list from docker daemon:", err) - return vars.DockerContainers + return vars.DockerContainerList() } var names []string - containersMetaDB := vars.ContainersMeta_DBs[util.GetHost()] + containersMetaDB := util.GetContainersMetaDB(util.GetHost()) if containersMetaDB == nil { - containersMetaDB, err := leveldb.OpenFile("leveldb/hosts/"+util.GetHost()+"/containersMeta", nil) - if err != nil { - panic(err) - } - vars.ContainersMeta_DBs[util.GetHost()] = containersMetaDB + return runningNames(result) } - containersMetaDB = vars.ContainersMeta_DBs[util.GetHost()] for i := range result { name := result[i].Name id := result[i].ID - names = append(names, name) + // Every container is recorded, so a stopped one can still be looked up + // by name; only running ones are streamed and shown as enabled. containersMetaDB.Put([]byte(name), []byte(id), nil) } + names = runningNames(result) return names } - -func (h *DaemonService) GetContainerImageNameByContainerID(ctx context.Context, containerID string) string { - result, err := h.DockerClient.GetContainerImageNameByContainerID(ctx, containerID) - if err != nil { - return "" - } - - return result -} diff --git a/application/backend/app/daemon/daemon_test.go b/application/backend/app/daemon/daemon_test.go index 38dc0cd..ef14774 100644 --- a/application/backend/app/daemon/daemon_test.go +++ b/application/backend/app/daemon/daemon_test.go @@ -3,36 +3,10 @@ package daemon import ( "context" "io" - "reflect" "strings" "testing" ) -func Test_validateMessage(t *testing.T) { - type args struct { - message string - } - tests := []struct { - name string - args args - want string - want1 bool - }{ - {"Bad message", args{message: string([]byte{10})}, "", false}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, got1 := validateMessage(tt.args.message) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("validateMessage() got = %v, want %v", got, tt.want) - } - if got1 != tt.want1 { - t.Errorf("validateMessage() got1 = %v, want %v", got1, tt.want1) - } - }) - } -} - func Test_streamDockerLogsRawTTY(t *testing.T) { ctrl := &DaemonService{} lines := []string{} diff --git a/application/backend/app/daemon/metricsstate_test.go b/application/backend/app/daemon/metricsstate_test.go new file mode 100644 index 0000000..8f91599 --- /dev/null +++ b/application/backend/app/daemon/metricsstate_test.go @@ -0,0 +1,87 @@ +package daemon + +import ( + "testing" + "time" + + "github.com/devforth/OnLogs/app/util" +) + +// finalizeStream clears droppedReplays; the /metrics total must not follow it +// down, or every stream restart looks like a counter reset. +func TestDroppedReplayTotalsSurviveFinalize(t *testing.T) { + h := NewDaemonService(nil) + + h.streamsMu.Lock() + h.streamIDs["c"] = 7 + h.streamsMu.Unlock() + + for i := 0; i < 3; i++ { + h.countDroppedReplay("c") + } + + if got := h.DroppedReplayTotals()[util.GetHost()+"/c"]; got != 3 { + t.Fatalf("before finalize: got %d, want 3", got) + } + + if !h.finalizeStream("c", 7) { + t.Fatal("finalizeStream did not claim the stream") + } + + if got := h.DroppedReplays("c"); got != 0 { + t.Errorf("per-stream counter should reset: got %d, want 0", got) + } + if got := h.DroppedReplayTotals()[util.GetHost()+"/c"]; got != 3 { + t.Errorf("monotonic total went backwards across finalize: got %d, want 3", got) + } + + h.countDroppedReplay("c") + if got := h.DroppedReplayTotals()[util.GetHost()+"/c"]; got != 4 { + t.Errorf("after restart: got %d, want 4", got) + } +} + +func TestCursorTimestampsRecorded(t *testing.T) { + h := NewDaemonService(nil) + + if len(h.CursorTimestamps()) != 0 { + t.Fatal("expected no cursors before ingestion") + } + + when := time.Date(2026, 8, 8, 10, 0, 0, 0, time.UTC) + h.saveCursor("host-a", "cont-a", when) + + got, ok := h.CursorTimestamps()["host-a/cont-a"] + if !ok { + t.Fatal("cursor not recorded") + } + if !got.Equal(when) { + t.Errorf("cursor: got %s, want %s", got, when) + } + + later := when.Add(time.Minute) + h.saveCursor("host-a", "cont-a", later) + if got := h.CursorTimestamps()["host-a/cont-a"]; !got.Equal(later) { + t.Errorf("cursor not advanced: got %s, want %s", got, later) + } +} + +func TestCursorTimestampsDroppedOnFinalize(t *testing.T) { + h := NewDaemonService(nil) + + h.streamsMu.Lock() + h.streamIDs["gone"] = 1 + h.streamsMu.Unlock() + + h.saveCursor(util.GetHost(), "gone", time.Now().UTC()) + if _, ok := h.CursorTimestamps()[util.GetHost()+"/gone"]; !ok { + t.Fatal("cursor not recorded") + } + + h.finalizeStream("gone", 1) + + // Otherwise a deliberately stopped container alerts forever. + if _, ok := h.CursorTimestamps()[util.GetHost()+"/gone"]; ok { + t.Error("cursor kept after the stream ended") + } +} diff --git a/application/backend/app/daemon/pipe_test.go b/application/backend/app/daemon/pipe_test.go new file mode 100644 index 0000000..315bcc3 --- /dev/null +++ b/application/backend/app/daemon/pipe_test.go @@ -0,0 +1,77 @@ +package daemon + +import ( + "context" + "io" + "strings" + "testing" + "time" +) + +// A reader that never reaches EOF, so StdCopy keeps producing and eventually +// parks in pw.Write once the consumer stops reading. +type endlessReader struct{ frame []byte } + +func (r *endlessReader) Read(p []byte) (int, error) { + n := copy(p, r.frame) + return n, nil +} +func (r *endlessReader) Close() error { return nil } + +func dockerFrame(payload string) []byte { + header := []byte{1, 0, 0, 0, 0, 0, 0, byte(len(payload))} + return append(header, []byte(payload)...) +} + +// Cancelling the context must not leave streamDockerLogs waiting on a StdCopy +// that is parked writing into a pipe nobody reads. If it does, the stream never +// finalises and EnsureStream refuses to restart that container ever again. +func TestStreamDockerLogsReturnsWhenCancelledMidWrite(t *testing.T) { + ctrl := &DaemonService{} + ctx, cancel := context.WithCancel(context.Background()) + + reader := &endlessReader{frame: dockerFrame("2026-01-01T00:00:00.000000000Z x\n")} + + done := make(chan error, 1) + go func() { + done <- ctrl.streamDockerLogs(ctx, reader, func(string) {}, true) + }() + + time.Sleep(50 * time.Millisecond) + cancel() + + select { + case <-done: + case <-time.After(5 * time.Second): + t.Fatal("streamDockerLogs never returned after cancellation; the container's stream is wedged for the life of the process") + } +} + +// A single line larger than the scanner's buffer must end the stream rather than +// wedge it, so the reconcile loop can re-attach. +func TestStreamDockerLogsReturnsOnAnOversizedLine(t *testing.T) { + ctrl := &DaemonService{} + + huge := "2026-01-01T00:00:00.000000000Z " + strings.Repeat("a", 2*1024*1024) + reader := io.NopCloser(strings.NewReader(string(dockerFrameLarge(huge)))) + + done := make(chan error, 1) + go func() { + done <- ctrl.streamDockerLogs(context.Background(), reader, func(string) {}, true) + }() + + select { + case err := <-done: + if err == nil { + t.Log("oversized line was tolerated") + } + case <-time.After(5 * time.Second): + t.Fatal("streamDockerLogs never returned on an oversized line") + } +} + +func dockerFrameLarge(payload string) []byte { + n := len(payload) + header := []byte{1, 0, 0, 0, byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n)} + return append(header, []byte(payload)...) +} diff --git a/application/backend/app/daemon/restart_test.go b/application/backend/app/daemon/restart_test.go new file mode 100644 index 0000000..cd522d9 --- /dev/null +++ b/application/backend/app/daemon/restart_test.go @@ -0,0 +1,168 @@ +package daemon + +import ( + "fmt" + "os" + "testing" + "time" + + "github.com/devforth/OnLogs/app/docker" + "github.com/devforth/OnLogs/app/util" + "github.com/devforth/OnLogs/app/vars" +) + +func corpusLine(index int) string { + ts := time.Date(2026, 2, 10, 12, 44, 3, index*1000000, time.UTC) + return ts.Format(time.RFC3339Nano) + fmt.Sprintf(" line-%03d", index) +} + +func storedRowCount(t *testing.T, host, container string) int { + t.Helper() + db := util.GetDB(host, container, "logs") + if db == nil { + t.Fatal("no logs database") + } + iter := db.NewIterator(nil, nil) + defer iter.Release() + + count := 0 + for iter.Next() { + count++ + } + return count +} + +// A container's stream is attached, lines are ingested, the process dies, and a +// new process attaches again. Docker's Since is floored to whole seconds and the +// resume cursor is deliberately rewound, so the second attach replays lines that +// are already stored. The in-memory dedupe ring does not survive the restart. +func TestRestartMidStreamStoresEachLineExactlyOnce(t *testing.T) { + host := util.GetHost() + container := "RestartUnderLoad" + _ = os.RemoveAll("leveldb/hosts/" + host + "/containers/" + container) + t.Cleanup(func() { _ = os.RemoveAll("leveldb/hosts/" + host + "/containers/" + container) }) + + vars.Mutex.Lock() + delete(vars.Container_Stat_Counter, host+"/"+container) + vars.Mutex.Unlock() + + const totalLines = 60 + const restartAfter = 40 + const replayFrom = 20 // the overlap window the rewound cursor re-serves + + emitted := map[string]struct{}{} + + first := NewDaemonService(nil) + db := util.GetDB(host, container, "logs") + if db == nil { + t.Fatal("could not open the logs database") + } + + storedThrough := first.storedThrough(host, container) + first.seedBoundaryFingerprints(host, container, storedThrough) + for i := 0; i < restartAfter; i++ { + line := corpusLine(i) + emitted[line] = struct{}{} + first.ingestLine(host, container, db, "", false, storedThrough, line) + } + + if got := storedRowCount(t, host, container); got != restartAfter { + t.Fatalf("first run stored %d rows, expected %d", got, restartAfter) + } + + second := NewDaemonService(nil) + + restartCursor := second.storedThrough(host, container) + if restartCursor.IsZero() { + t.Fatal("no cursor was persisted, so a restart cannot know where it left off") + } + second.seedBoundaryFingerprints(host, container, restartCursor) + + for i := replayFrom; i < totalLines; i++ { + line := corpusLine(i) + emitted[line] = struct{}{} + second.ingestLine(host, container, db, "", false, restartCursor, line) + } + + stored := storedRowCount(t, host, container) + if stored != len(emitted) { + t.Fatalf("stored %d rows for %d distinct emitted lines: %d duplicate row(s) survived the restart", + stored, len(emitted), stored-len(emitted)) + } + if stored != totalLines { + t.Fatalf("stored %d rows, expected %d", stored, totalLines) + } + + if dropped := second.DroppedReplays(container); dropped != restartAfter-replayFrom { + t.Errorf("expected %d replayed lines to be dropped and counted, got %d", + restartAfter-replayFrom, dropped) + } + + assertNoDuplicateMessages(t, host, container) +} + +func assertNoDuplicateMessages(t *testing.T, host, container string) { + t.Helper() + db := util.GetDB(host, container, "logs") + iter := db.NewIterator(nil, nil) + defer iter.Release() + + seen := map[string]struct{}{} + for iter.Next() { + message := string(iter.Value()) + if _, exists := seen[message]; exists { + t.Errorf("message stored more than once: %q", message) + } + seen[message] = struct{}{} + } +} + +func TestRestartKeepsADistinctLineSharingTheCursorTimestamp(t *testing.T) { + host := util.GetHost() + container := "SameNanosecondBoundary" + _ = os.RemoveAll("leveldb/hosts/" + host + "/containers/" + container) + t.Cleanup(func() { _ = os.RemoveAll("leveldb/hosts/" + host + "/containers/" + container) }) + + db := util.GetDB(host, container, "logs") + if db == nil { + t.Fatal("could not open the logs database") + } + + ts := time.Date(2026, 2, 10, 12, 44, 3, 123456789, time.UTC).Format(time.RFC3339Nano) + first := NewDaemonService(nil) + + if !first.ingestLine(host, container, db, "", false, time.Time{}, ts+" first at this nanosecond") { + t.Fatal("the first line was not stored") + } + + second := NewDaemonService(nil) + cursor := second.storedThrough(host, container) + second.seedBoundaryFingerprints(host, container, cursor) + + if second.ingestLine(host, container, db, "", false, cursor, ts+" first at this nanosecond") { + t.Error("a replayed line at the cursor timestamp was stored again") + } + if !second.ingestLine(host, container, db, "", false, cursor, ts+" second at this nanosecond") { + t.Error("a distinct line sharing the cursor's nanosecond was silently discarded") + } + + assertNoDuplicateMessages(t, host, container) + if got := storedRowCount(t, host, container); got != 2 { + t.Fatalf("expected both distinct lines to be stored, got %d rows", got) + } +} + +func TestRunningNamesSkipsExitedContainers(t *testing.T) { + result := []docker.ContainerNamesResult{ + {Name: "alive", ID: "1", Running: true}, + {Name: "exited", ID: "2", Running: false}, + {Name: "", ID: "3", Running: true}, + {Name: "alive-too", ID: "4", Running: true}, + } + + names := runningNames(result) + + if len(names) != 2 || names[0] != "alive" || names[1] != "alive-too" { + t.Fatalf("expected only the running, named containers, got %v", names) + } +} diff --git a/application/backend/app/db/db.go b/application/backend/app/db/db.go index 2f50a59..349226d 100644 --- a/application/backend/app/db/db.go +++ b/application/backend/app/db/db.go @@ -1,6 +1,7 @@ package db import ( + "strings" "time" "github.com/devforth/OnLogs/app/util" @@ -8,9 +9,57 @@ import ( "github.com/syndtr/goleveldb/leveldb" ) +const ( + tokenTTL = 24 * time.Hour + legacyClaimed = "was used" +) + +// Stored as "|"; an empty claimedAt means never claimed. +type tokenRecord struct { + expiry time.Time + claimedAt time.Time + claimed bool +} + +func encodeToken(r tokenRecord) string { + claimed := "" + if r.claimed { + claimed = r.claimedAt.UTC().Format(time.RFC3339Nano) + } + return r.expiry.UTC().Format(time.RFC3339Nano) + "|" + claimed +} + +func decodeToken(raw string) (tokenRecord, bool) { + // Tokens issued before the expiry was tracked carry this literal and have no + // recoverable timestamps; they stay valid so agents survive the upgrade. + if raw == legacyClaimed { + return tokenRecord{claimed: true}, true + } + + expiryStr, claimedStr, ok := strings.Cut(raw, "|") + if !ok { + return tokenRecord{}, false + } + expiry, err := time.Parse(time.RFC3339Nano, expiryStr) + if err != nil { + return tokenRecord{}, false + } + r := tokenRecord{expiry: expiry} + if claimedStr != "" { + claimedAt, err := time.Parse(time.RFC3339Nano, claimedStr) + if err != nil { + return tokenRecord{}, false + } + r.claimedAt = claimedAt + r.claimed = true + } + return r, true +} + func CreateOnLogsToken() string { token := util.GenerateJWTSecret() - to_put := time.Now().UTC().Add(24 * time.Hour).String() + to_put := encodeToken(tokenRecord{expiry: time.Now().UTC().Add(tokenTTL)}) + err := vars.TokensDB.Put([]byte(token), []byte(to_put), nil) if err != nil { vars.TokensDB.Close() @@ -25,39 +74,49 @@ func CreateOnLogsToken() string { } func IsTokenExists(token string) bool { - iter := vars.TokensDB.NewIterator(nil, nil) - defer iter.Release() - iter.First() - if string(iter.Key()) == token { - vars.TokensDB.Put([]byte(token), []byte("was used"), nil) + if token == "" || vars.TokensDB == nil { + return false + } + + raw, err := vars.TokensDB.Get([]byte(token), nil) + if err != nil { + return false + } + + record, ok := decodeToken(string(raw)) + if !ok { + return false + } + if record.claimed { return true } + if record.expiry.Before(time.Now()) { + return false + } + + record.claimedAt = time.Now() + record.claimed = true + vars.TokensDB.Put([]byte(token), []byte(encodeToken(record)), nil) + return true +} + +func reapExpiredTokens(db *leveldb.DB) { + iter := db.NewIterator(nil, nil) + defer iter.Release() + for iter.Next() { - if string(iter.Key()) == token { - vars.TokensDB.Put([]byte(token), []byte("was used"), nil) - return true + record, ok := decodeToken(string(iter.Value())) + if !ok || (!record.claimed && record.expiry.Before(time.Now())) { + db.Delete(iter.Key(), nil) } } - return false } func DeleteUnusedTokens() { for { - db := vars.TokensDB - iter := db.NewIterator(nil, nil) - for iter.Next() { - wasUsed := string(iter.Value()) - if wasUsed == "was used" { - continue - } - - created, _ := time.Parse("2006-01-02 15:04:05.999999999 -0700 MST", string(wasUsed)) - if created.Before(time.Now()) { - db.Delete(iter.Key(), nil) - } - } - iter.Release() - db.Close() time.Sleep(time.Hour * 1) + if vars.TokensDB != nil { + reapExpiredTokens(vars.TokensDB) + } } } diff --git a/application/backend/app/db/db_test.go b/application/backend/app/db/db_test.go deleted file mode 100644 index 3a122a6..0000000 --- a/application/backend/app/db/db_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package db - -import ( - "testing" -) - -func TestIsTokenExists(t *testing.T) { - type args struct { - token string - } - tests := []struct { - name string - args args - want bool - }{ - {"Bad token", args{token: "fasdfadsf"}, false}, - {"Valid token", args{token: CreateOnLogsToken()}, true}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := IsTokenExists(tt.args.token); got != tt.want { - t.Errorf("IsTokenExists() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestCreateOnLogsToken(t *testing.T) { - token := CreateOnLogsToken() - if !IsTokenExists(token) { - t.Error("Invalid token") - } -} diff --git a/application/backend/app/db/reap_test.go b/application/backend/app/db/reap_test.go new file mode 100644 index 0000000..9e0fc08 --- /dev/null +++ b/application/backend/app/db/reap_test.go @@ -0,0 +1,56 @@ +package db + +import ( + "testing" + "time" + + "github.com/devforth/OnLogs/app/vars" +) + +func TestReapExpiredTokensRemovesOnlyUnclaimedExpiredOnes(t *testing.T) { + claimed := "reap-claimed-probe" + unclaimedFresh := "reap-unclaimed-fresh-probe" + unclaimedStale := "reap-unclaimed-stale-probe" + garbage := "reap-garbage-probe" + t.Cleanup(func() { + for _, k := range []string{claimed, unclaimedFresh, unclaimedStale, garbage} { + vars.TokensDB.Delete([]byte(k), nil) + } + }) + + past := time.Now().UTC().Add(-time.Hour) + future := time.Now().UTC().Add(time.Hour) + vars.TokensDB.Put([]byte(claimed), []byte(encodeToken(tokenRecord{expiry: past, claimedAt: past, claimed: true})), nil) + vars.TokensDB.Put([]byte(unclaimedFresh), []byte(encodeToken(tokenRecord{expiry: future})), nil) + vars.TokensDB.Put([]byte(unclaimedStale), []byte(encodeToken(tokenRecord{expiry: past})), nil) + vars.TokensDB.Put([]byte(garbage), []byte("not a timestamp at all"), nil) + + reapExpiredTokens(vars.TokensDB) + + for _, keep := range []string{claimed, unclaimedFresh} { + if has, _ := vars.TokensDB.Has([]byte(keep), nil); !has { + t.Errorf("%s was reaped but should have been kept", keep) + } + } + for _, gone := range []string{unclaimedStale, garbage} { + if has, _ := vars.TokensDB.Has([]byte(gone), nil); has { + t.Errorf("%s survived the reaper", gone) + } + } +} + +func TestLegacyClaimedTokensKeepWorking(t *testing.T) { + legacy := "legacy-was-used-probe" + if err := vars.TokensDB.Put([]byte(legacy), []byte(legacyClaimed), nil); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { vars.TokensDB.Delete([]byte(legacy), nil) }) + + if !IsTokenExists(legacy) { + t.Fatal("an agent token issued before the upgrade stopped working") + } + reapExpiredTokens(vars.TokensDB) + if has, _ := vars.TokensDB.Has([]byte(legacy), nil); !has { + t.Fatal("an agent token issued before the upgrade was reaped") + } +} diff --git a/application/backend/app/db/token_test.go b/application/backend/app/db/token_test.go new file mode 100644 index 0000000..397b802 --- /dev/null +++ b/application/backend/app/db/token_test.go @@ -0,0 +1,101 @@ +package db + +import ( + "strings" + "testing" + "time" + + "github.com/devforth/OnLogs/app/vars" +) + +func TestIsTokenExistsKeepsTheTokenAuditable(t *testing.T) { + token := CreateOnLogsToken() + + before, err := vars.TokensDB.Get([]byte(token), nil) + if err != nil { + t.Fatal(err) + } + issued := strings.Split(string(before), "|")[0] + if _, err := time.Parse(time.RFC3339Nano, issued); err != nil { + t.Fatalf("a fresh token does not carry a parseable expiry: %q", before) + } + + if !IsTokenExists(token) { + t.Fatal("a freshly minted token was rejected") + } + + after, err := vars.TokensDB.Get([]byte(token), nil) + if err != nil { + t.Fatal(err) + } + if !strings.HasPrefix(string(after), issued+"|") { + t.Fatalf("using a token destroyed its expiry: %q -> %q", before, after) + } + if strings.HasSuffix(string(after), "|") { + t.Fatalf("using a token did not record when it was claimed: %q", after) + } +} + +func TestIsTokenExistsWritesOnlyOnFirstUse(t *testing.T) { + token := CreateOnLogsToken() + + if !IsTokenExists(token) { + t.Fatal("a freshly minted token was rejected") + } + first, _ := vars.TokensDB.Get([]byte(token), nil) + + time.Sleep(5 * time.Millisecond) + if !IsTokenExists(token) { + t.Fatal("a claimed token was rejected") + } + second, _ := vars.TokensDB.Get([]byte(token), nil) + + if string(first) != string(second) { + t.Fatalf("every ingested log line rewrites the token record: %q -> %q", first, second) + } +} + +func TestIsTokenExistsRejectsTheEmptyToken(t *testing.T) { + if IsTokenExists("") { + t.Fatal("the empty token authenticates") + } +} + +func TestIsTokenExistsRejectsAnUnclaimedExpiredToken(t *testing.T) { + expired := "expired-token-probe" + stamp := time.Now().UTC().Add(-time.Hour).Format(time.RFC3339Nano) + "|" + if err := vars.TokensDB.Put([]byte(expired), []byte(stamp), nil); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { vars.TokensDB.Delete([]byte(expired), nil) }) + + if IsTokenExists(expired) { + t.Fatalf("an unclaimed token that expired an hour ago still authenticates (%q)", stamp) + } +} + +func TestIsTokenExistsRejectsAGarbageRecord(t *testing.T) { + junk := "garbage-token-probe" + if err := vars.TokensDB.Put([]byte(junk), []byte("not a timestamp at all"), nil); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { vars.TokensDB.Delete([]byte(junk), nil) }) + + if IsTokenExists(junk) { + t.Fatal("a token record with no recoverable expiry still authenticates") + } +} + +func TestDeleteUnusedTokensKeepsTheSharedHandleOpen(t *testing.T) { + token := CreateOnLogsToken() + + go DeleteUnusedTokens() + time.Sleep(250 * time.Millisecond) + + if !IsTokenExists(token) { + t.Error("a valid token stopped being accepted once the token reaper ran") + } + if IsTokenExists("") { + t.Error("the empty token authenticates once the token reaper ran") + } +} diff --git a/application/backend/app/docker/docker_client.go b/application/backend/app/docker/docker_client.go index c4499f0..21e7788 100644 --- a/application/backend/app/docker/docker_client.go +++ b/application/backend/app/docker/docker_client.go @@ -15,8 +15,9 @@ type DockerService struct { } type ContainerNamesResult struct { - Name string - ID string + Name string + ID string + Running bool } func (s *DockerService) GetContainerNames(ctx context.Context) ([]ContainerNamesResult, error) { @@ -31,7 +32,7 @@ func (s *DockerService) GetContainerNames(ctx context.Context) ([]ContainerNames if len(c.Names) > 0 { name = strings.TrimPrefix(c.Names[0], "/") } - res = append(res, ContainerNamesResult{Name: name, ID: c.ID}) + res = append(res, ContainerNamesResult{Name: name, ID: c.ID, Running: c.State == "running"}) } return res, nil } diff --git a/application/backend/app/groups/groups.go b/application/backend/app/groups/groups.go new file mode 100644 index 0000000..c9a24cd --- /dev/null +++ b/application/backend/app/groups/groups.go @@ -0,0 +1,148 @@ +// Package groups stores per-user, named sets of host/service pairs. It owns the +// key layout and the JSON encoding so no caller has to reproduce either. +package groups + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + + "github.com/devforth/OnLogs/app/util" + "github.com/devforth/OnLogs/app/vars" + "github.com/syndtr/goleveldb/leveldb" + ldbutil "github.com/syndtr/goleveldb/leveldb/util" +) + +const ( + MaxNameBytes = 64 + MaxMembers = 500 + MaxGroupsPerUser = 100 + + // The only byte that cannot appear in a group name, which is what keeps one + // user's key range out of another's. + separator = "\x00" +) + +type Member struct { + Host string `json:"host"` + Service string `json:"service"` +} + +type Group struct { + Name string `json:"name"` + Members []Member `json:"members"` +} + +func ValidateGroupName(name string) error { + if name == "" { + return errors.New("Group name can not be empty") + } + if len(name) > MaxNameBytes { + return fmt.Errorf("Group name can not be longer than %d bytes", MaxNameBytes) + } + if strings.ContainsRune(name, 0) { + return errors.New("Group name can not contain a NUL byte") + } + if strings.TrimSpace(name) != name { + return errors.New("Group name can not start or end with whitespace") + } + return nil +} + +// Every member reaches util.GetDB and a /view/:host/:service URL, so both halves +// have to survive the same single-path-component guard those already apply. +func ValidateMembers(members []Member) error { + if len(members) > MaxMembers { + return fmt.Errorf("A group can not hold more than %d members", MaxMembers) + } + for _, member := range members { + if !util.IsSafeName(member.Host) || !util.IsSafeName(member.Service) { + return errors.New("Invalid group member") + } + } + return nil +} + +func Key(username string, name string) ([]byte, error) { + if strings.ContainsRune(username, 0) { + return nil, errors.New("Invalid username") + } + if err := ValidateGroupName(name); err != nil { + return nil, err + } + return []byte(username + separator + name), nil +} + +func Load(username string, name string) ([]Member, bool, error) { + key, err := Key(username, name) + if err != nil { + return nil, false, err + } + + raw, err := vars.GroupsDB.Get(key, nil) + if errors.Is(err, leveldb.ErrNotFound) { + return nil, false, nil + } + if err != nil { + return nil, false, err + } + + members := []Member{} + if err := json.Unmarshal(raw, &members); err != nil { + return nil, false, err + } + return members, true, nil +} + +func Store(username string, name string, members []Member) error { + key, err := Key(username, name) + if err != nil { + return err + } + if err := ValidateMembers(members); err != nil { + return err + } + + if members == nil { + members = []Member{} + } + raw, err := json.Marshal(members) + if err != nil { + return err + } + return vars.GroupsDB.Put(key, raw, nil) +} + +// Deleting a key that is not there is not an error, which is what makes the +// route idempotent. +func Delete(username string, name string) error { + key, err := Key(username, name) + if err != nil { + return err + } + return vars.GroupsDB.Delete(key, nil) +} + +func List(username string) ([]Group, error) { + if strings.ContainsRune(username, 0) { + return nil, errors.New("Invalid username") + } + + prefix := username + separator + iter := vars.GroupsDB.NewIterator(ldbutil.BytesPrefix([]byte(prefix)), nil) + defer iter.Release() + + list := []Group{} + for iter.Next() { + members := []Member{} + if err := json.Unmarshal(iter.Value(), &members); err != nil { + continue + } + list = append(list, Group{ + Name: strings.TrimPrefix(string(iter.Key()), prefix), + Members: members, + }) + } + return list, iter.Error() +} diff --git a/application/backend/app/groups/groups_test.go b/application/backend/app/groups/groups_test.go new file mode 100644 index 0000000..298e58f --- /dev/null +++ b/application/backend/app/groups/groups_test.go @@ -0,0 +1,171 @@ +package groups + +import ( + "bytes" + "strings" + "testing" +) + +func TestValidateGroupName(t *testing.T) { + cases := []struct { + label string + name string + wantErr bool + }{ + {"plain name", "backend", false}, + {"name with a space", "backend services", false}, + {"exactly 64 bytes", strings.Repeat("a", 64), false}, + {"multi-byte name inside the byte limit", strings.Repeat("Γ©", 32), false}, + {"empty", "", true}, + {"65 bytes", strings.Repeat("a", 65), true}, + {"multi-byte name over the byte limit", strings.Repeat("Γ©", 33), true}, + {"NUL byte", "web\x00admin", true}, + {"NUL byte at the end", "web\x00", true}, + {"leading whitespace", " backend", true}, + {"trailing whitespace", "backend ", true}, + {"trailing newline", "backend\n", true}, + {"only whitespace", " ", true}, + } + + for _, c := range cases { + t.Run(c.label, func(t *testing.T) { + err := ValidateGroupName(c.name) + if c.wantErr && err == nil { + t.Fatalf("ValidateGroupName(%q) = nil, want an error", c.name) + } + if !c.wantErr && err != nil { + t.Fatalf("ValidateGroupName(%q) = %v, want nil", c.name, err) + } + }) + } +} + +func TestValidateMembers(t *testing.T) { + cases := []struct { + label string + members []Member + wantErr bool + }{ + {"empty list", []Member{}, false}, + {"one member", []Member{{Host: "host1", Service: "api"}}, false}, + {"exactly 500 members", makeMembers(500), false}, + {"501 members", makeMembers(501), true}, + {"empty host", []Member{{Host: "", Service: "api"}}, true}, + {"empty service", []Member{{Host: "host1", Service: ""}}, true}, + {"host is a parent traversal", []Member{{Host: "..", Service: "api"}}, true}, + {"service is a parent traversal", []Member{{Host: "host1", Service: ".."}}, true}, + {"host is a dot", []Member{{Host: ".", Service: "api"}}, true}, + {"service has a path separator", []Member{{Host: "host1", Service: "a/b"}}, true}, + {"host has a path separator", []Member{{Host: "a/b", Service: "api"}}, true}, + {"service has a backslash", []Member{{Host: "host1", Service: `a\b`}}, true}, + {"service has a NUL byte", []Member{{Host: "host1", Service: "a\x00b"}}, true}, + {"one bad member among good ones", []Member{ + {Host: "host1", Service: "api"}, + {Host: "host1", Service: ".."}, + {Host: "host2", Service: "web"}, + }, true}, + } + + for _, c := range cases { + t.Run(c.label, func(t *testing.T) { + err := ValidateMembers(c.members) + if c.wantErr && err == nil { + t.Fatalf("ValidateMembers(%v) = nil, want an error", c.members) + } + if !c.wantErr && err != nil { + t.Fatalf("ValidateMembers(%v) = %v, want nil", c.members, err) + } + }) + } +} + +// The key separator is what keeps one user's groups out of another's, so a name +// carrying its own separator must never be storable. +func TestKeySeparatorCannotBeForged(t *testing.T) { + if err := ValidateGroupName("\x00victim's group"); err == nil { + t.Fatal("a group name containing the key separator was accepted") + } + + forged, err := Key("attacker", "\x00victim\x00group") + if err == nil { + t.Fatalf("Key accepted a name containing the separator: %q", forged) + } + + mine, err := Key("attacker", "mine") + if err != nil { + t.Fatalf("Key rejected a valid name: %v", err) + } + if !bytes.Equal(mine, []byte("attacker\x00mine")) { + t.Fatalf("Key(attacker, mine) = %q, want %q", mine, "attacker\x00mine") + } + + if _, err := Key("attac\x00ker", "mine"); err == nil { + t.Fatal("Key accepted a username containing the separator") + } +} + +func TestStoreLoadDeleteRoundTrip(t *testing.T) { + members := []Member{{Host: "host1", Service: "api"}, {Host: "host2", Service: "web"}} + if err := Store("alice", "backend", members); err != nil { + t.Fatalf("Store: %v", err) + } + t.Cleanup(func() { Delete("alice", "backend") }) + + loaded, found, err := Load("alice", "backend") + if err != nil || !found { + t.Fatalf("Load: found=%v err=%v", found, err) + } + if len(loaded) != 2 || loaded[0] != members[0] || loaded[1] != members[1] { + t.Fatalf("Load returned %v, want %v", loaded, members) + } + + if err := Delete("alice", "backend"); err != nil { + t.Fatalf("Delete: %v", err) + } + if _, found, _ := Load("alice", "backend"); found { + t.Fatal("the group is still readable after Delete") + } + // The UI can double-fire delete, so a second one is not an error. + if err := Delete("alice", "backend"); err != nil { + t.Fatalf("second Delete: %v", err) + } +} + +// List keys off a username prefix, so a username that is a prefix of another +// must not pull in the longer user's groups. +func TestListIsScopedToOneUser(t *testing.T) { + Store("bob", "shared", []Member{{Host: "host1", Service: "api"}}) + Store("bobby", "other", []Member{{Host: "host1", Service: "web"}}) + t.Cleanup(func() { + Delete("bob", "shared") + Delete("bobby", "other") + }) + + bobs, err := List("bob") + if err != nil { + t.Fatalf("List: %v", err) + } + if len(bobs) != 1 || bobs[0].Name != "shared" { + t.Fatalf("List(bob) = %v, want just the group named shared", bobs) + } + if _, found, _ := Load("bob", "other"); found { + t.Fatal("bob can read bobby's group") + } +} + +func TestStoreRejectsInvalidInput(t *testing.T) { + if err := Store("carol", "bad\x00name", nil); err == nil { + t.Error("Store accepted a name containing the key separator") + } + if err := Store("carol", "traversal", []Member{{Host: "..", Service: "api"}}); err == nil { + t.Error("Store accepted a member that escapes its directory") + } +} + +func makeMembers(n int) []Member { + members := make([]Member, 0, n) + for i := 0; i < n; i++ { + members = append(members, Member{Host: "host1", Service: "svc" + strings.Repeat("x", i%5)}) + } + return members +} diff --git a/application/backend/app/hostalias/hostalias.go b/application/backend/app/hostalias/hostalias.go new file mode 100644 index 0000000..f2fb620 --- /dev/null +++ b/application/backend/app/hostalias/hostalias.go @@ -0,0 +1,50 @@ +package hostalias + +import ( + "errors" + "fmt" + "strings" + + "github.com/devforth/OnLogs/app/util" + "github.com/devforth/OnLogs/app/vars" +) + +const MaxAliasBytes = 64 + +func Validate(host string, alias string) error { + if !util.IsSafeName(host) { + return errors.New("Invalid host") + } + if len(alias) > MaxAliasBytes { + return fmt.Errorf("Display name can not be longer than %d bytes", MaxAliasBytes) + } + if strings.ContainsRune(alias, 0) { + return errors.New("Display name can not contain a NUL byte") + } + if strings.TrimSpace(alias) != alias { + return errors.New("Display name can not start or end with whitespace") + } + return nil +} + +// An empty alias clears it, so the sidebar falls back to the real hostname. +func Set(host string, alias string) error { + if err := Validate(host, alias); err != nil { + return err + } + if alias == "" { + return vars.AliasDB.Delete([]byte(host), nil) + } + return vars.AliasDB.Put([]byte(host), []byte(alias), nil) +} + +func All() (map[string]string, error) { + iter := vars.AliasDB.NewIterator(nil, nil) + defer iter.Release() + + aliases := map[string]string{} + for iter.Next() { + aliases[string(iter.Key())] = string(iter.Value()) + } + return aliases, iter.Error() +} diff --git a/application/backend/app/hostalias/hostalias_test.go b/application/backend/app/hostalias/hostalias_test.go new file mode 100644 index 0000000..2167bc0 --- /dev/null +++ b/application/backend/app/hostalias/hostalias_test.go @@ -0,0 +1,76 @@ +package hostalias + +import ( + "strings" + "testing" + + "github.com/devforth/OnLogs/app/vars" +) + +func TestValidateRejectsUnsafeInput(t *testing.T) { + cases := []struct { + label string + host string + alias string + wantErr bool + }{ + {"plain", "myhost", "prod box", false}, + {"clearing", "myhost", "", false}, + {"exactly 64 bytes", "myhost", strings.Repeat("a", 64), false}, + {"65 bytes", "myhost", strings.Repeat("a", 65), true}, + {"NUL in alias", "myhost", "prod\x00box", true}, + {"leading space", "myhost", " prod", true}, + {"trailing space", "myhost", "prod ", true}, + {"host escaping its directory", "..", "prod", true}, + {"host with a separator", "a/b", "prod", true}, + {"empty host", "", "prod", true}, + } + + for _, c := range cases { + t.Run(c.label, func(t *testing.T) { + err := Validate(c.host, c.alias) + if c.wantErr && err == nil { + t.Fatalf("Validate(%q, %q) = nil, want an error", c.host, c.alias) + } + if !c.wantErr && err != nil { + t.Fatalf("Validate(%q, %q) = %v, want nil", c.host, c.alias, err) + } + }) + } +} + +func TestSetAndClearRoundTrip(t *testing.T) { + const host = "alias-round-trip-host" + t.Cleanup(func() { vars.AliasDB.Delete([]byte(host), nil) }) + + if err := Set(host, "prod box"); err != nil { + t.Fatalf("Set: %v", err) + } + aliases, err := All() + if err != nil { + t.Fatalf("All: %v", err) + } + if aliases[host] != "prod box" { + t.Fatalf("All()[%q] = %q, want %q", host, aliases[host], "prod box") + } + + if err := Set(host, ""); err != nil { + t.Fatalf("clearing: %v", err) + } + aliases, _ = All() + if _, present := aliases[host]; present { + t.Fatalf("the alias survived being cleared: %q", aliases[host]) + } +} + +func TestSetRejectsInvalidWithoutWriting(t *testing.T) { + const host = "alias-reject-host" + t.Cleanup(func() { vars.AliasDB.Delete([]byte(host), nil) }) + + if err := Set(host, strings.Repeat("a", 65)); err == nil { + t.Error("Set accepted an oversized display name") + } + if aliases, _ := All(); aliases[host] != "" { + t.Errorf("a rejected alias was stored anyway: %q", aliases[host]) + } +} diff --git a/application/backend/app/metrics/collect.go b/application/backend/app/metrics/collect.go new file mode 100644 index 0000000..1ae95b5 --- /dev/null +++ b/application/backend/app/metrics/collect.go @@ -0,0 +1,122 @@ +package metrics + +import ( + "fmt" + "io" + "math" + "runtime" + runtimemetrics "runtime/metrics" + "sync/atomic" + "time" + + "github.com/devforth/OnLogs/app/statistics" + "github.com/devforth/OnLogs/app/util" + "github.com/devforth/OnLogs/app/vars" + "golang.org/x/sys/unix" +) + +// Not /gc/heap/live:bytes, which reads 0 until the first GC completes. +const heapMetric = "/memory/classes/heap/objects:bytes" + +// The previous scrape's duration, as float64 bits: the current one cannot time +// itself, since the value goes into the body it is timing. +var scrapeDuration atomic.Uint64 + +func recordScrapeDuration(elapsed time.Duration) { + scrapeDuration.Store(math.Float64bits(elapsed.Seconds())) +} + +func lastScrapeDuration() float64 { + return math.Float64frombits(scrapeDuration.Load()) +} + +// Local streams only: vars.Active_Daemon_Streams holds bare container names and +// never contains agent-forwarded ones. +func writeStreamUp(w io.Writer) { + active := vars.ActiveStreams() + if len(active) == 0 { + return + } + + host := util.GetHost() + writeHeader(w, "onlogs_stream_up", "gauge", "1 while a local container's log stream is attached.") + for _, container := range sortedStrings(active) { + fmt.Fprintf(w, "onlogs_stream_up{host=\"%s\",container=\"%s\"} 1\n", + escapeLabelValue(host), escapeLabelValue(container)) + } +} + +// An empty map omits the family rather than exporting a zero, so a series only +// appears once there is something real behind it. +func writePerContainer[V any](w io.Writer, name, metricType, help string, values map[string]V, value func(V) int64) { + if len(values) == 0 { + return + } + + writeHeader(w, name, metricType, help) + for _, location := range sortedKeys(values) { + host, container := splitLocation(location) + fmt.Fprintf(w, "%s{host=\"%s\",container=\"%s\"} %d\n", + name, escapeLabelValue(host), escapeLabelValue(container), value(values[location])) + } +} + +// Raw timestamp, not a derived lag: a quiet container's lag grows forever and +// means nothing. The alert pairs this with a log-line rate. +func writeCursors(w io.Writer, ds daemonState) { + if ds == nil { + return + } + writePerContainer(w, "onlogs_stream_cursor_timestamp_seconds", "gauge", + "Timestamp of the newest log line ingested for a container.", + ds.CursorTimestamps(), func(ts time.Time) int64 { return ts.Unix() }) +} + +func writeDroppedReplays(w io.Writer, ds daemonState) { + if ds == nil { + return + } + writePerContainer(w, "onlogs_dropped_replay_lines_total", "counter", + "Log lines dropped because a stream replayed something already stored.", + ds.DroppedReplayTotals(), func(n uint64) int64 { return int64(n) }) +} + +func writeProcess(w io.Writer) { + writeHeader(w, "onlogs_stats_workers", "gauge", "Statistics workers running, one per streamed container.") + fmt.Fprintf(w, "onlogs_stats_workers %d\n", statistics.WorkerCount()) + + writeHeader(w, "onlogs_websocket_connections", "gauge", "Live log viewers connected.") + fmt.Fprintf(w, "onlogs_websocket_connections %d\n", vars.TotalConnections()) + + writeHeader(w, "onlogs_goroutines", "gauge", "Goroutines running.") + fmt.Fprintf(w, "onlogs_goroutines %d\n", runtime.NumGoroutine()) + + samples := []runtimemetrics.Sample{{Name: heapMetric}} + runtimemetrics.Read(samples) + writeHeader(w, "onlogs_heap_bytes", "gauge", "Live heap objects in bytes.") + fmt.Fprintf(w, "onlogs_heap_bytes %d\n", samples[0].Value.Uint64()) + + writeHeader(w, "onlogs_login_failures_total", "counter", "Rejected login attempts.") + fmt.Fprintf(w, "onlogs_login_failures_total %d\n", vars.LoginFailures.Load()) + + writeHeader(w, "onlogs_login_blocked_total", "counter", "Login attempts refused by the rate limiter.") + fmt.Fprintf(w, "onlogs_login_blocked_total %d\n", vars.LoginBlocked.Load()) + + writeHeader(w, "onlogs_metrics_scrape_duration_seconds", "gauge", + "Time the previous scrape took to render.") + fmt.Fprintf(w, "onlogs_metrics_scrape_duration_seconds %g\n", lastScrapeDuration()) +} + +// Bavail, not Bfree: the difference is the root reserve, which OnLogs cannot use. +func writeFilesystem(w io.Writer) { + var stat unix.Statfs_t + if err := unix.Statfs(".", &stat); err != nil { + return + } + + writeHeader(w, "onlogs_filesystem_size_bytes", "gauge", "Size of the filesystem holding the logs.") + fmt.Fprintf(w, "onlogs_filesystem_size_bytes %d\n", stat.Blocks*uint64(stat.Bsize)) + + writeHeader(w, "onlogs_filesystem_avail_bytes", "gauge", "Space available to OnLogs on that filesystem.") + fmt.Fprintf(w, "onlogs_filesystem_avail_bytes %d\n", stat.Bavail*uint64(stat.Bsize)) +} diff --git a/application/backend/app/metrics/collect_test.go b/application/backend/app/metrics/collect_test.go new file mode 100644 index 0000000..32d7bc1 --- /dev/null +++ b/application/backend/app/metrics/collect_test.go @@ -0,0 +1,204 @@ +package metrics + +import ( + "context" + "net/http" + "net/http/httptest" + "os" + "strconv" + "strings" + "testing" + "time" + + "github.com/devforth/OnLogs/app/statistics" + "github.com/devforth/OnLogs/app/util" + "github.com/devforth/OnLogs/app/vars" +) + +// app/daemon owns the tests for the real state; this covers rendering only. +type fakeDaemon struct { + dropped map[string]uint64 + cursors map[string]time.Time +} + +func (f fakeDaemon) DroppedReplayTotals() map[string]uint64 { return f.dropped } +func (f fakeDaemon) CursorTimestamps() map[string]time.Time { return f.cursors } + +// Value of one series from a scrape, and whether it appeared. +func sample(t *testing.T, body string, series string) (float64, bool) { + t.Helper() + + for _, line := range strings.Split(body, "\n") { + if strings.HasPrefix(line, "#") || line == "" { + continue + } + i := strings.LastIndex(line, " ") + if i < 0 || line[:i] != series { + continue + } + value, err := strconv.ParseFloat(line[i+1:], 64) + if err != nil { + t.Fatalf("series %s has a non-numeric value %q", series, line[i+1:]) + } + return value, true + } + return 0, false +} + +func body(t *testing.T, ds daemonState) string { + t.Helper() + os.Setenv("METRICS_TOKEN", testToken) + t.Cleanup(func() { os.Unsetenv("METRICS_TOKEN") }) + + req := httptest.NewRequest(http.MethodGet, "/api/v1/metrics", nil) + req.Header.Set("Authorization", "Bearer "+testToken) + rr := httptest.NewRecorder() + Handler(ds).ServeHTTP(rr, req) + return rr.Body.String() +} + +func TestStreamUpTracksActiveStreams(t *testing.T) { + host := util.GetHost() + for _, c := range vars.ActiveStreams() { + vars.RemoveActiveStream(c) + } + + vars.AddActiveStream("metrics-stream-a") + vars.AddActiveStream("metrics-stream-b") + defer func() { + vars.RemoveActiveStream("metrics-stream-a") + vars.RemoveActiveStream("metrics-stream-b") + }() + + out := body(t, nil) + for _, container := range []string{"metrics-stream-a", "metrics-stream-b"} { + series := `onlogs_stream_up{host="` + host + `",container="` + container + `"}` + value, ok := sample(t, out, series) + if !ok { + t.Errorf("%s missing", series) + continue + } + if value != 1 { + t.Errorf("%s: got %v, want 1", series, value) + } + } + + vars.RemoveActiveStream("metrics-stream-a") + if _, ok := sample(t, body(t, nil), `onlogs_stream_up{host="`+host+`",container="metrics-stream-a"}`); ok { + t.Error("stopped stream still exported") + } +} + +func TestCursorTimestampOmittedWhenUnknown(t *testing.T) { + if strings.Contains(body(t, fakeDaemon{}), "onlogs_stream_cursor_timestamp_seconds{") { + t.Error("cursor series emitted with no cursors recorded; it must be omitted, not zero") + } + + when := time.Date(2026, 8, 8, 10, 0, 0, 0, time.UTC) + ds := fakeDaemon{cursors: map[string]time.Time{"cursor-host/cursor-container": when}} + + series := `onlogs_stream_cursor_timestamp_seconds{host="cursor-host",container="cursor-container"}` + value, ok := sample(t, body(t, ds), series) + if !ok { + t.Fatalf("%s missing", series) + } + if value != float64(when.Unix()) { + t.Errorf("%s: got %v, want %v", series, value, when.Unix()) + } +} + +func TestStatsWorkersTracksRegistry(t *testing.T) { + before, _ := sample(t, body(t, nil), "onlogs_stats_workers") + + statistics.EnsureWorker(context.Background(), "metrics-worker-host", "metrics-worker-container") + defer statistics.StopWorker("metrics-worker-host", "metrics-worker-container") + + after, ok := sample(t, body(t, nil), "onlogs_stats_workers") + if !ok { + t.Fatal("onlogs_stats_workers missing") + } + if after != before+1 { + t.Errorf("onlogs_stats_workers: got %v, want %v", after, before+1) + } +} + +func TestLoginCountersExported(t *testing.T) { + vars.LoginFailures.Store(4) + vars.LoginBlocked.Store(2) + defer func() { + vars.LoginFailures.Store(0) + vars.LoginBlocked.Store(0) + }() + + out := body(t, nil) + if value, ok := sample(t, out, "onlogs_login_failures_total"); !ok || value != 4 { + t.Errorf("onlogs_login_failures_total: got %v (present=%v), want 4", value, ok) + } + if value, ok := sample(t, out, "onlogs_login_blocked_total"); !ok || value != 2 { + t.Errorf("onlogs_login_blocked_total: got %v (present=%v), want 2", value, ok) + } +} + +// Plausibility only: the exact values are not ours to predict. +func TestProcessGaugesPresent(t *testing.T) { + out := body(t, nil) + + for _, series := range []string{ + "onlogs_goroutines", + "onlogs_heap_bytes", + "onlogs_filesystem_size_bytes", + "onlogs_filesystem_avail_bytes", + "onlogs_websocket_connections", + "onlogs_metrics_scrape_duration_seconds", + } { + value, ok := sample(t, out, series) + if !ok { + t.Errorf("%s missing", series) + continue + } + if value < 0 { + t.Errorf("%s: got %v, want >= 0", series, value) + } + } + + if value, _ := sample(t, out, "onlogs_goroutines"); value < 1 { + t.Errorf("onlogs_goroutines: got %v, want >= 1", value) + } + if value, _ := sample(t, out, "onlogs_heap_bytes"); value <= 0 { + t.Errorf("onlogs_heap_bytes: got %v, want > 0", value) + } + if value, _ := sample(t, out, "onlogs_filesystem_size_bytes"); value <= 0 { + t.Errorf("onlogs_filesystem_size_bytes: got %v, want > 0", value) + } +} + +func TestScrapeDurationIsPreviousScrape(t *testing.T) { + scrapeDuration.Store(0) + + if value, _ := sample(t, body(t, nil), "onlogs_metrics_scrape_duration_seconds"); value != 0 { + t.Errorf("first scrape: got %v, want 0", value) + } + if value, _ := sample(t, body(t, nil), "onlogs_metrics_scrape_duration_seconds"); value <= 0 { + t.Errorf("second scrape: got %v, want > 0", value) + } +} + +func TestDroppedReplayExported(t *testing.T) { + ds := fakeDaemon{dropped: map[string]uint64{"replay-host/replay-container": 1}} + + series := `onlogs_dropped_replay_lines_total{host="replay-host",container="replay-container"}` + value, ok := sample(t, body(t, ds), series) + if !ok { + t.Fatalf("%s missing", series) + } + if value != 1 { + t.Errorf("%s: got %v, want 1", series, value) + } +} + +// Keeps testing.B out of the helpers that take *testing.T. +func benchScrape() { + req := httptest.NewRequest(http.MethodGet, "/api/v1/metrics", nil) + req.Header.Set("Authorization", "Bearer "+testToken) + Handler(nil).ServeHTTP(httptest.NewRecorder(), req) +} diff --git a/application/backend/app/metrics/metrics.go b/application/backend/app/metrics/metrics.go new file mode 100644 index 0000000..b563adb --- /dev/null +++ b/application/backend/app/metrics/metrics.go @@ -0,0 +1,126 @@ +// Package metrics serves the Prometheus exposition. Nothing here may touch the +// filesystem or the Docker daemon: a scrape must not compete with ingestion. +package metrics + +import ( + "crypto/subtle" + "fmt" + "io" + "net/http" + "os" + "sort" + "strings" + "time" + + "github.com/devforth/OnLogs/app/containerdb" +) + +// Set at link time with -ldflags "-X .../app/metrics.Version=x.y.z". +var Version = "dev" + +const contentType = "text/plain; version=0.0.4; charset=utf-8" + +// Satisfied by *daemon.DaemonService. An interface so this package does not +// import app/daemon, and so rendering is testable without a docker stream. +type daemonState interface { + DroppedReplayTotals() map[string]uint64 + CursorTimestamps() map[string]time.Time +} + +// A nil ds is valid and omits the per-container ingestion series. +func Handler(ds daemonState) http.HandlerFunc { + return func(w http.ResponseWriter, req *http.Request) { + // Before the method check: an unauthorized caller learns nothing. + if !authorized(req) { + w.WriteHeader(http.StatusUnauthorized) + return + } + if req.Method != http.MethodGet { + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + started := time.Now() + w.Header().Set("Content-Type", contentType) + write(w, ds) + recordScrapeDuration(time.Since(started)) + } +} + +// An unset METRICS_TOKEN is the feature being off, not an open endpoint. +func authorized(req *http.Request) bool { + token := os.Getenv("METRICS_TOKEN") + if token == "" { + return false + } + + offered := strings.TrimPrefix(req.Header.Get("Authorization"), "Bearer ") + if offered == req.Header.Get("Authorization") { + return false // no "Bearer " prefix at all + } + return subtle.ConstantTimeCompare([]byte(offered), []byte(token)) == 1 +} + +func write(w io.Writer, ds daemonState) { + writeLogLines(w) + writeStreamUp(w) + writeCursors(w, ds) + writeDroppedReplays(w, ds) + writeSizes(w) + writeProcess(w) + writeFilesystem(w) + + writeHeader(w, "onlogs_build_info", "gauge", "Build information, always 1.") + fmt.Fprintf(w, "onlogs_build_info{version=\"%s\"} 1\n", escapeLabelValue(Version)) +} + +func sortedStrings(values []string) []string { + sorted := append([]string{}, values...) + sort.Strings(sorted) + return sorted +} + +func writeLogLines(w io.Writer) { + counts := containerdb.LogLineCounts() + if len(counts) == 0 { + return + } + + writeHeader(w, "onlogs_log_lines_total", "counter", "Log lines stored, by severity.") + for _, location := range sortedKeys(counts) { + host, container := splitLocation(location) + for _, level := range sortedKeys(counts[location]) { + fmt.Fprintf(w, "onlogs_log_lines_total{host=\"%s\",container=\"%s\",level=\"%s\"} %d\n", + escapeLabelValue(host), escapeLabelValue(container), escapeLabelValue(level), + counts[location][level]) + } + } +} + +func writeHeader(w io.Writer, name string, metricType string, help string) { + fmt.Fprintf(w, "# HELP %s %s\n", name, help) + fmt.Fprintf(w, "# TYPE %s %s\n", name, metricType) +} + +// util.IsSafeName rejects a slash in either half, so the first one separates them. +func splitLocation(location string) (string, string) { + host, container, found := strings.Cut(location, "/") + if !found { + return location, "" + } + return host, container +} + +func escapeLabelValue(value string) string { + return strings.NewReplacer(`\`, `\\`, `"`, `\"`, "\n", `\n`).Replace(value) +} + +// Sorted so a scrape is byte-for-byte stable between calls. +func sortedKeys[V any](m map[string]V) []string { + keys := make([]string, 0, len(m)) + for key := range m { + keys = append(keys, key) + } + sort.Strings(keys) + return keys +} diff --git a/application/backend/app/metrics/metrics_test.go b/application/backend/app/metrics/metrics_test.go new file mode 100644 index 0000000..aac1711 --- /dev/null +++ b/application/backend/app/metrics/metrics_test.go @@ -0,0 +1,164 @@ +package metrics + +import ( + "net/http" + "net/http/httptest" + "os" + "strings" + "testing" + + "github.com/devforth/OnLogs/app/containerdb" + "github.com/devforth/OnLogs/app/util" +) + +const testToken = "metrics-package-test-token" + +func scrape(t *testing.T, method string, auth string) *httptest.ResponseRecorder { + t.Helper() + + req := httptest.NewRequest(method, "/api/v1/metrics", nil) + if auth != "" { + req.Header.Set("Authorization", auth) + } + rr := httptest.NewRecorder() + Handler(nil).ServeHTTP(rr, req) + return rr +} + +func TestMetricsUnauthorized(t *testing.T) { + os.Unsetenv("METRICS_TOKEN") + + rr := scrape(t, http.MethodGet, "") + if rr.Code != http.StatusUnauthorized { + t.Errorf("status: got %d, want %d", rr.Code, http.StatusUnauthorized) + } + if body := rr.Body.String(); body != "" { + t.Errorf("body: got %q, want empty", body) + } + if ct := rr.Header().Get("Content-Type"); ct != "" { + t.Errorf("Content-Type: got %q, want unset", ct) + } +} + +func TestMetricsWrongToken(t *testing.T) { + os.Setenv("METRICS_TOKEN", testToken) + defer os.Unsetenv("METRICS_TOKEN") + + for _, auth := range []string{"Bearer wrong", "Bearer ", "", testToken, "Basic " + testToken} { + rr := scrape(t, http.MethodGet, auth) + if rr.Code != http.StatusUnauthorized { + t.Errorf("auth %q: got %d, want %d", auth, rr.Code, http.StatusUnauthorized) + } + } +} + +func TestMetricsAuthBeforeMethod(t *testing.T) { + os.Setenv("METRICS_TOKEN", testToken) + defer os.Unsetenv("METRICS_TOKEN") + + rr := scrape(t, http.MethodPost, "") + if rr.Code != http.StatusUnauthorized { + t.Errorf("unauthenticated POST: got %d, want %d", rr.Code, http.StatusUnauthorized) + } +} + +func TestMetricsWrongMethod(t *testing.T) { + os.Setenv("METRICS_TOKEN", testToken) + defer os.Unsetenv("METRICS_TOKEN") + + rr := scrape(t, http.MethodPost, "Bearer "+testToken) + if rr.Code != http.StatusMethodNotAllowed { + t.Errorf("authenticated POST: got %d, want %d", rr.Code, http.StatusMethodNotAllowed) + } +} + +func TestMetricsServesWithValidToken(t *testing.T) { + os.Setenv("METRICS_TOKEN", testToken) + defer os.Unsetenv("METRICS_TOKEN") + + rr := scrape(t, http.MethodGet, "Bearer "+testToken) + if rr.Code != http.StatusOK { + t.Fatalf("status: got %d, want 200", rr.Code) + } + if ct := rr.Header().Get("Content-Type"); ct != contentType { + t.Errorf("Content-Type: got %q, want %q", ct, contentType) + } + if !strings.Contains(rr.Body.String(), "onlogs_build_info{version=") { + t.Errorf("build info missing from:\n%s", rr.Body.String()) + } +} + +// What promtool checks, without needing promtool: a HELP and a TYPE per family, +// and no series emitted twice. +func TestMetricsGoldenParses(t *testing.T) { + os.Setenv("METRICS_TOKEN", testToken) + defer os.Unsetenv("METRICS_TOKEN") + + host := util.GetHost() + db := util.GetDB(host, "golden-container", "logs") + if db == nil { + t.Fatal("no logs db") + } + defer os.RemoveAll("leveldb/hosts/" + host + "/containers/golden-container") + if err := containerdb.PutLogMessage(db, host, "golden-container", []string{ + "2026-08-08T10:00:00.000000000Z", "ERROR golden", + }); err != nil { + t.Fatalf("PutLogMessage: %v", err) + } + + body := scrape(t, http.MethodGet, "Bearer "+testToken).Body.String() + + helped := map[string]bool{} + typed := map[string]bool{} + seen := map[string]bool{} + + for _, line := range strings.Split(body, "\n") { + if line == "" { + continue + } + if strings.HasPrefix(line, "# HELP ") { + helped[strings.Fields(line)[2]] = true + continue + } + if strings.HasPrefix(line, "# TYPE ") { + typed[strings.Fields(line)[2]] = true + continue + } + if strings.HasPrefix(line, "#") { + continue + } + + series := line + if i := strings.LastIndex(line, " "); i >= 0 { + series = line[:i] + } + if seen[series] { + t.Errorf("duplicate series: %s", series) + } + seen[series] = true + + name := series + if i := strings.Index(series, "{"); i >= 0 { + name = series[:i] + } + if !helped[name] { + t.Errorf("%s has no # HELP before its first sample", name) + } + if !typed[name] { + t.Errorf("%s has no # TYPE before its first sample", name) + } + } + + if len(seen) == 0 { + t.Fatal("no samples emitted") + } +} + +// util.IsSafeName constrains container names today; the writer must not rely on it. +func TestLabelValuesAreEscaped(t *testing.T) { + got := escapeLabelValue(`a"b\c` + "\n" + `d`) + want := `a\"b\\c\nd` + if got != want { + t.Errorf("escapeLabelValue: got %q, want %q", got, want) + } +} diff --git a/application/backend/app/metrics/sizes.go b/application/backend/app/metrics/sizes.go new file mode 100644 index 0000000..13f0adb --- /dev/null +++ b/application/backend/app/metrics/sizes.go @@ -0,0 +1,78 @@ +package metrics + +import ( + "context" + "fmt" + "io" + "os" + "sync/atomic" + "time" + + "github.com/devforth/OnLogs/app/containerdb" + "github.com/devforth/OnLogs/app/util" +) + +// Long because producing it walks every stored container. +const sizeRefreshInterval = 5 * time.Minute + +type sizeSnapshot struct { + perContainer map[string]int64 + total int64 +} + +// nil until the first refresh, so a scrape during startup omits the size series +// rather than reporting an empty disk. +var sizes atomic.Pointer[sizeSnapshot] + +func setSizes(snapshot *sizeSnapshot) { sizes.Store(snapshot) } + +// RefreshSizes performs one walk. +func RefreshSizes() { + perContainer, total := util.LogsSizes() + setSizes(&sizeSnapshot{perContainer: perContainer, total: total}) +} + +// Deliberately its own ticker, not the streamer's 60s reconcile loop: too +// frequent for a full walk, and that loop already carries an unsynchronised write. +func StartSizeRefresher(ctx context.Context) { + RefreshSizes() + + ticker := time.NewTicker(sizeRefreshInterval) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + RefreshSizes() + } + } +} + +func writeSizes(w io.Writer) { + if snapshot := sizes.Load(); snapshot != nil { + writeHeader(w, "onlogs_logs_size_bytes", "gauge", + "Total size of stored logs, the number the retention quota is compared against.") + fmt.Fprintf(w, "onlogs_logs_size_bytes %d\n", snapshot.total) + + if len(snapshot.perContainer) > 0 { + writeHeader(w, "onlogs_container_db_size_bytes", "gauge", "Stored log size per container.") + for _, location := range sortedKeys(snapshot.perContainer) { + host, container := splitLocation(location) + fmt.Fprintf(w, "onlogs_container_db_size_bytes{host=\"%s\",container=\"%s\"} %d\n", + escapeLabelValue(host), escapeLabelValue(container), snapshot.perContainer[location]) + } + } + } + + // Omitted rather than guessed if it does not parse. + if limit, err := util.ParseHumanReadableSize(os.Getenv("MAX_LOGS_SIZE")); err == nil { + writeHeader(w, "onlogs_logs_size_limit_bytes", "gauge", "MAX_LOGS_SIZE in bytes.") + fmt.Fprintf(w, "onlogs_logs_size_limit_bytes %d\n", limit) + } + + writeHeader(w, "onlogs_retention_deleted_lines_total", "counter", + "Log lines deleted by the size quota.") + fmt.Fprintf(w, "onlogs_retention_deleted_lines_total %d\n", containerdb.RetentionDeletedLines()) +} diff --git a/application/backend/app/metrics/sizes_test.go b/application/backend/app/metrics/sizes_test.go new file mode 100644 index 0000000..e8afa9c --- /dev/null +++ b/application/backend/app/metrics/sizes_test.go @@ -0,0 +1,146 @@ +package metrics + +import ( + "os" + "strconv" + "strings" + "testing" + "time" + + "github.com/devforth/OnLogs/app/containerdb" +) + +// n container directories on disk that the scrape must ignore. +func containerDirsOnDisk(t testing.TB, host string, n int) { + t.Helper() + + base := "leveldb/hosts/" + host + "/containers/" + for i := 0; i < n; i++ { + path := base + "bench" + strconv.Itoa(i) + if err := os.MkdirAll(path+"/logs", 0700); err != nil { + t.Fatalf("mkdir: %v", err) + } + if err := os.WriteFile(path+"/logs/CURRENT", []byte("x"), 0600); err != nil { + t.Fatalf("write: %v", err) + } + } + t.Cleanup(func() { os.RemoveAll("leveldb/hosts/" + host) }) +} + +func countSeries(body string, name string) int { + count := 0 + for _, line := range strings.Split(body, "\n") { + if strings.HasPrefix(line, name+"{") { + count++ + } + } + return count +} + +// 200 containers on disk while the snapshot holds 2: a handler that walked would +// emit 200 series. Deterministic, unlike timing it. +func TestScrapeIgnoresContainersOnDisk(t *testing.T) { + containerDirsOnDisk(t, "ignored-host", 200) + + setSizes(&sizeSnapshot{ + perContainer: map[string]int64{ + "cached-host/cached-a": 1024, + "cached-host/cached-b": 2048, + }, + total: 3072, + }) + t.Cleanup(func() { setSizes(nil) }) + + out := body(t, nil) + + if got := countSeries(out, "onlogs_container_db_size_bytes"); got != 2 { + t.Errorf("container size series: got %d, want 2 (the snapshot); a walk would give 200", got) + } + if value, ok := sample(t, out, "onlogs_logs_size_bytes"); !ok || value != 3072 { + t.Errorf("onlogs_logs_size_bytes: got %v (present=%v), want 3072", value, ok) + } + if value, ok := sample(t, out, `onlogs_container_db_size_bytes{host="cached-host",container="cached-a"}`); !ok || value != 1024 { + t.Errorf("per-container size: got %v (present=%v), want 1024", value, ok) + } +} + +func TestSizeSnapshotBeforeFirstRefresh(t *testing.T) { + setSizes(nil) + t.Cleanup(func() { setSizes(nil) }) + + done := make(chan string, 1) + go func() { done <- body(t, nil) }() + + select { + case out := <-done: + if strings.Contains(out, "onlogs_container_db_size_bytes{") { + t.Error("per-container size emitted with no snapshot") + } + if _, ok := sample(t, out, "onlogs_logs_size_bytes"); ok { + t.Error("total size emitted with no snapshot") + } + case <-time.After(5 * time.Second): + t.Fatal("handler blocked waiting for the first refresh") + } +} + +func TestLogsSizeLimitFromEnv(t *testing.T) { + os.Setenv("MAX_LOGS_SIZE", "2GB") + defer os.Unsetenv("MAX_LOGS_SIZE") + + value, ok := sample(t, body(t, nil), "onlogs_logs_size_limit_bytes") + if !ok { + t.Fatal("onlogs_logs_size_limit_bytes missing") + } + if value != 2*1000*1000*1000 && value != 2*1024*1024*1024 { + t.Errorf("onlogs_logs_size_limit_bytes: got %v, want 2GB in bytes", value) + } +} + +func TestLogsSizeLimitOmittedWhenUnparseable(t *testing.T) { + os.Setenv("MAX_LOGS_SIZE", "not-a-size") + defer os.Unsetenv("MAX_LOGS_SIZE") + + if _, ok := sample(t, body(t, nil), "onlogs_logs_size_limit_bytes"); ok { + t.Error("limit emitted for an unparseable MAX_LOGS_SIZE") + } +} + +func TestRetentionDeletedCounterExported(t *testing.T) { + before := containerdb.RetentionDeletedLines() + containerdb.CountRetentionDeleted(5) + + value, ok := sample(t, body(t, nil), "onlogs_retention_deleted_lines_total") + if !ok { + t.Fatal("onlogs_retention_deleted_lines_total missing") + } + if value != float64(before+5) { + t.Errorf("onlogs_retention_deleted_lines_total: got %v, want %v", value, before+5) + } +} + +// Snapshot of 200 containers with 200 more on disk: measures rendering, not walking. +func BenchmarkMetricsHandler(b *testing.B) { + for _, onDisk := range []int{0, 200} { + b.Run(strconv.Itoa(onDisk)+"-dirs-on-disk", func(b *testing.B) { + containerDirsOnDisk(b, "bench-host-"+strconv.Itoa(onDisk), onDisk) + + snapshot := &sizeSnapshot{perContainer: map[string]int64{}} + for i := 0; i < 200; i++ { + snapshot.perContainer["h/c"+strconv.Itoa(i)] = int64(i * 1024) + snapshot.total += int64(i * 1024) + } + setSizes(snapshot) + b.Cleanup(func() { setSizes(nil) }) + + os.Setenv("METRICS_TOKEN", testToken) + b.Cleanup(func() { os.Unsetenv("METRICS_TOKEN") }) + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + benchScrape() + } + }) + } +} diff --git a/application/backend/app/routes/edituser_test.go b/application/backend/app/routes/edituser_test.go new file mode 100644 index 0000000..1269b42 --- /dev/null +++ b/application/backend/app/routes/edituser_test.go @@ -0,0 +1,139 @@ +package routes + +import ( + "bytes" + "encoding/json" + "net/http" + "net/http/httptest" + "os" + "testing" + + "github.com/devforth/OnLogs/app/userdb" + "github.com/devforth/OnLogs/app/util" + "github.com/devforth/OnLogs/app/vars" +) + +func TestEditUserActuallyChangesThePassword(t *testing.T) { + os.Setenv("ADMIN_USERNAME", "admin") + + userdb.CreateUser("rotateme", "the-old-password") + t.Cleanup(func() { userdb.DeleteUser("rotateme") }) + + body, _ := json.Marshal(map[string]string{"login": "rotateme", "password": "the-new-password"}) + req, _ := http.NewRequest("POST", "/api/v1/editUser", bytes.NewBuffer(body)) + req.AddCookie(&http.Cookie{Name: "onlogs-cookie", Value: util.CreateJWT("admin")}) + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.EditUser).ServeHTTP(rr, req) + + if code := rr.Result().StatusCode; code != http.StatusOK { + t.Fatalf("editUser returned %d: %s", code, rr.Body.String()) + } + + var response map[string]interface{} + json.Unmarshal(rr.Body.Bytes(), &response) + if response["error"] != nil { + t.Fatalf("editUser reported an error: %v", response["error"]) + } + + if !userdb.CheckUserPassword("rotateme", "the-new-password") { + t.Error("editUser reported success but the new password does not work") + } + if userdb.CheckUserPassword("rotateme", "the-old-password") { + t.Error("editUser reported success but the old password still works") + } +} + +func TestEditUserRejectsAnEmptyPassword(t *testing.T) { + os.Setenv("ADMIN_USERNAME", "admin") + + userdb.CreateUser("emptyrotate", "a-real-password") + t.Cleanup(func() { userdb.DeleteUser("emptyrotate") }) + + body, _ := json.Marshal(map[string]string{"login": "emptyrotate", "password": ""}) + req, _ := http.NewRequest("POST", "/api/v1/editUser", bytes.NewBuffer(body)) + req.AddCookie(&http.Cookie{Name: "onlogs-cookie", Value: util.CreateJWT("admin")}) + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.EditUser).ServeHTTP(rr, req) + + if userdb.CheckUserPassword("emptyrotate", "") { + t.Fatal("an empty password was accepted") + } + if !userdb.CheckUserPassword("emptyrotate", "a-real-password") { + t.Error("the original password stopped working") + } +} + +func TestGetHostsReadsFavouritesPerHost(t *testing.T) { + + os.RemoveAll("leveldb/hosts") + os.MkdirAll("leveldb/hosts/FavHostA/containers/shared", 0o700) + os.MkdirAll("leveldb/hosts/FavHostB/containers/shared", 0o700) + + starred := favouriteKey("someuser", "FavHostB", "shared") + t.Cleanup(func() { + vars.FavsDB.Delete(starred, nil) + os.RemoveAll("leveldb/hosts") + }) + + if err := vars.FavsDB.Put(starred, nil, nil); err != nil { + t.Fatal(err) + } + + req, _ := http.NewRequest("GET", "/api/v1/getHosts", nil) + req.AddCookie(&http.Cookie{Name: "onlogs-cookie", Value: util.CreateJWT("someuser")}) + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.GetHosts).ServeHTTP(rr, req) + + var hosts []struct { + Host string `json:"host"` + Services []struct { + ServiceName string `json:"serviceName"` + IsFavorite bool `json:"isFavorite"` + } `json:"services"` + } + if err := json.Unmarshal(rr.Body.Bytes(), &hosts); err != nil { + t.Fatalf("unmarshal: %v -- body %s", err, rr.Body.String()) + } + + favourites := map[string]bool{} + for _, host := range hosts { + for _, service := range host.Services { + favourites[host.Host+"/"+service.ServiceName] = service.IsFavorite + } + } + + if !favourites["FavHostB/shared"] { + t.Error("the starred container on FavHostB is not reported as a favourite") + } + if favourites["FavHostA/shared"] { + t.Error("a container that was never starred on FavHostA is reported as a favourite") + } +} + +func TestFavouritesAreScopedToTheUserWhoSetThem(t *testing.T) { + userdb.CreateUser("favuser", "favpass") + userdb.CreateUser("otheruser", "otherpass") + t.Cleanup(func() { + userdb.DeleteUser("favuser") + userdb.DeleteUser("otheruser") + vars.FavsDB.Delete(favouriteKey("favuser", "h", "svc"), nil) + vars.FavsDB.Delete(favouriteKey("otheruser", "h", "svc"), nil) + }) + + body, _ := json.Marshal(map[string]string{"host": "h", "service": "svc"}) + req, _ := http.NewRequest("POST", "/api/v1/changeFavorite", bytes.NewBuffer(body)) + req.AddCookie(&http.Cookie{Name: "onlogs-cookie", Value: util.CreateJWT("favuser")}) + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.ChangeFavourite).ServeHTTP(rr, req) + + if code := rr.Result().StatusCode; code != http.StatusOK { + t.Fatalf("changeFavorite returned %d: %s", code, rr.Body.String()) + } + + if starred, _ := vars.FavsDB.Has(favouriteKey("favuser", "h", "svc"), nil); !starred { + t.Error("the user's own favourite was not recorded") + } + if starred, _ := vars.FavsDB.Has(favouriteKey("otheruser", "h", "svc"), nil); starred { + t.Error("one user's star was applied to another user") + } +} diff --git a/application/backend/app/routes/groups_test.go b/application/backend/app/routes/groups_test.go new file mode 100644 index 0000000..718c084 --- /dev/null +++ b/application/backend/app/routes/groups_test.go @@ -0,0 +1,322 @@ +package routes + +import ( + "encoding/json" + "net/http" + "slices" + "testing" + + "github.com/devforth/OnLogs/app/groups" + "github.com/devforth/OnLogs/app/hostalias" +) + +func groupNames(t *testing.T, body []byte) []string { + t.Helper() + + var list []groups.Group + if err := json.Unmarshal(body, &list); err != nil { + t.Fatalf("unmarshalling the group list: %v -- body: %s", err, body) + } + names := []string{} + for _, group := range list { + names = append(names, group.Name) + } + return names +} + +func TestGroupsAreIsolatedPerUser(t *testing.T) { + t.Cleanup(func() { groups.Delete("testuser", "isolated") }) + + status, body := call(t, testCtrl.CreateGroup, authedRequest(t, "testuser", "POST", "/", map[string]interface{}{ + "name": "isolated", + "members": []map[string]string{{"host": "Test1", "service": "containerTest1"}}, + })) + if status != http.StatusOK { + t.Fatalf("creating the group returned %d: %s", status, body) + } + + status, body = call(t, testCtrl.GetGroups, authedRequest(t, "viewer", "GET", "/", nil)) + if status != http.StatusOK { + t.Fatalf("viewer's getGroups returned %d: %s", status, body) + } + if slices.Contains(groupNames(t, body), "isolated") { + t.Fatalf("viewer can read testuser's group: %s", body) + } + + call(t, testCtrl.DeleteGroup, authedRequest(t, "viewer", "POST", "/", map[string]string{"name": "isolated"})) + if _, found, _ := groups.Load("testuser", "isolated"); !found { + t.Fatal("viewer's deleteGroup removed testuser's group") + } + + call(t, testCtrl.UpdateGroup, authedRequest(t, "viewer", "POST", "/", map[string]interface{}{ + "name": "isolated", + "members": []map[string]string{}, + })) + members, found, _ := groups.Load("testuser", "isolated") + if !found || len(members) != 1 { + t.Fatalf("viewer's updateGroup changed testuser's group: found=%v members=%v", found, members) + } +} + +func TestGroupCRUDRoundTrip(t *testing.T) { + t.Cleanup(func() { + groups.Delete("testuser", "backend") + groups.Delete("testuser", "backend renamed") + }) + + status, body := call(t, testCtrl.CreateGroup, authedRequest(t, "testuser", "POST", "/", map[string]interface{}{ + "name": "backend", + "members": []map[string]string{ + {"host": "Test1", "service": "containerTest1"}, + {"host": "Test2", "service": "containerTest2"}, + }, + })) + if status != http.StatusOK { + t.Fatalf("createGroup returned %d: %s", status, body) + } + + status, body = call(t, testCtrl.GetGroups, authedRequest(t, "testuser", "GET", "/", nil)) + if status != http.StatusOK || !slices.Contains(groupNames(t, body), "backend") { + t.Fatalf("getGroups returned %d without the new group: %s", status, body) + } + + status, body = call(t, testCtrl.UpdateGroup, authedRequest(t, "testuser", "POST", "/", map[string]interface{}{ + "name": "backend", + "newName": "backend renamed", + "members": []map[string]string{{"host": "Test1", "service": "containerTest1"}}, + })) + if status != http.StatusOK { + t.Fatalf("updateGroup returned %d: %s", status, body) + } + + if _, found, _ := groups.Load("testuser", "backend"); found { + t.Fatal("the old name still resolves after a rename") + } + members, found, _ := groups.Load("testuser", "backend renamed") + if !found || len(members) != 1 || members[0].Service != "containerTest1" { + t.Fatalf("after the update the group holds %v", members) + } + + status, body = call(t, testCtrl.DeleteGroup, authedRequest(t, "testuser", "POST", "/", map[string]string{ + "name": "backend renamed", + })) + if status != http.StatusOK { + t.Fatalf("deleteGroup returned %d: %s", status, body) + } + if _, found, _ := groups.Load("testuser", "backend renamed"); found { + t.Fatal("the group survived deleteGroup") + } +} + +func TestGroupRoutesRejectUnauthenticated(t *testing.T) { + + for _, route := range []struct { + name string + handler http.HandlerFunc + method string + body interface{} + }{ + {"getGroups", testCtrl.GetGroups, "GET", nil}, + {"createGroup", testCtrl.CreateGroup, "POST", map[string]interface{}{"name": "nope", "members": []string{}}}, + {"updateGroup", testCtrl.UpdateGroup, "POST", map[string]interface{}{"name": "nope", "members": []string{}}}, + {"deleteGroup", testCtrl.DeleteGroup, "POST", map[string]string{"name": "nope"}}, + } { + t.Run(route.name, func(t *testing.T) { + status, body := call(t, route.handler, authedRequest(t, "", route.method, "/", route.body)) + if status != http.StatusUnauthorized { + t.Fatalf("%s returned %d for an unauthenticated request: %s", route.name, status, body) + } + }) + } + + if _, found, _ := groups.Load("", "nope"); found { + groups.Delete("", "nope") + t.Fatal("an unauthenticated request wrote a group") + } +} + +func TestCreateGroupRejectsDuplicateName(t *testing.T) { + t.Cleanup(func() { groups.Delete("testuser", "duplicated") }) + + create := func() (int, []byte) { + return call(t, testCtrl.CreateGroup, authedRequest(t, "testuser", "POST", "/", map[string]interface{}{ + "name": "duplicated", + "members": []map[string]string{{"host": "Test1", "service": "containerTest1"}}, + })) + } + + if status, body := create(); status != http.StatusOK { + t.Fatalf("the first createGroup returned %d: %s", status, body) + } + if status, body := create(); status != http.StatusConflict { + t.Fatalf("the second createGroup returned %d, want 409: %s", status, body) + } +} + +func TestUpdateGroupOnMissingGroupIsNotFound(t *testing.T) { + + status, body := call(t, testCtrl.UpdateGroup, authedRequest(t, "testuser", "POST", "/", map[string]interface{}{ + "name": "never created", + "members": []map[string]string{{"host": "Test1", "service": "containerTest1"}}, + })) + if status != http.StatusNotFound { + t.Fatalf("updateGroup on a missing group returned %d, want 404: %s", status, body) + } + if _, found, _ := groups.Load("testuser", "never created"); found { + groups.Delete("testuser", "never created") + t.Fatal("updateGroup silently created the group") + } +} + +// The UI can double-fire delete, so the second one is not an error. +func TestDeleteGroupIsIdempotent(t *testing.T) { + + for attempt := 0; attempt < 2; attempt++ { + status, body := call(t, testCtrl.DeleteGroup, authedRequest(t, "testuser", "POST", "/", map[string]string{ + "name": "was never there", + })) + if status != http.StatusOK { + t.Fatalf("deleteGroup attempt %d returned %d, want 200: %s", attempt+1, status, body) + } + } +} + +func TestGroupRoutesRejectMalformedInput(t *testing.T) { + + cases := []struct { + label string + handler http.HandlerFunc + body interface{} + }{ + {"name carrying the key separator", testCtrl.CreateGroup, map[string]interface{}{ + "name": "web\x00admin", "members": []map[string]string{}, + }}, + {"empty name", testCtrl.CreateGroup, map[string]interface{}{ + "name": "", "members": []map[string]string{}, + }}, + {"oversized name", testCtrl.CreateGroup, map[string]interface{}{ + "name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "members": []map[string]string{}, + }}, + {"member escaping its directory", testCtrl.CreateGroup, map[string]interface{}{ + "name": "traversal", "members": []map[string]string{{"host": "..", "service": "api"}}, + }}, + {"member with a path separator", testCtrl.CreateGroup, map[string]interface{}{ + "name": "separator", "members": []map[string]string{{"host": "Test1", "service": "a/b"}}, + }}, + {"member with an empty service", testCtrl.CreateGroup, map[string]interface{}{ + "name": "empty member", "members": []map[string]string{{"host": "Test1", "service": ""}}, + }}, + {"delete with a forged name", testCtrl.DeleteGroup, map[string]string{"name": "web\x00admin"}}, + {"update with a forged new name", testCtrl.UpdateGroup, map[string]interface{}{ + "name": "backend", "newName": "web\x00admin", "members": []map[string]string{}, + }}, + } + + for _, c := range cases { + t.Run(c.label, func(t *testing.T) { + status, body := call(t, c.handler, authedRequest(t, "testuser", "POST", "/", c.body)) + if status != http.StatusBadRequest { + t.Fatalf("returned %d, want 400: %s", status, body) + } + }) + } +} + +func TestCreateGroupCapsGroupsPerUser(t *testing.T) { + + names := []string{} + t.Cleanup(func() { + for _, name := range names { + groups.Delete("someuser", name) + } + }) + + for i := 0; i < groups.MaxGroupsPerUser; i++ { + name := "capped-" + string(rune('a'+i/26)) + string(rune('a'+i%26)) + names = append(names, name) + if err := groups.Store("someuser", name, []groups.Member{}); err != nil { + t.Fatalf("seeding group %d: %v", i, err) + } + } + + names = append(names, "one too many") + status, body := call(t, testCtrl.CreateGroup, authedRequest(t, "someuser", "POST", "/", map[string]interface{}{ + "name": "one too many", + "members": []map[string]string{}, + })) + if status != http.StatusBadRequest { + t.Fatalf("createGroup past the cap returned %d, want 400: %s", status, body) + } + if _, found, _ := groups.Load("someuser", "one too many"); found { + t.Fatal("createGroup stored a group past the cap") + } +} + +// DISABLE_AUTH is accepted as-is, not fixed here: util.GetUserFromJWT still +// returns "" for a cookie-less request, so every such user shares one bucket. +// Favourites already behave this way. This pins it as a decision. +func TestDisableAuthSharesOneGroupBucket(t *testing.T) { + t.Setenv("DISABLE_AUTH", "true") + t.Cleanup(func() { groups.Delete("", "shared bucket") }) + + status, body := call(t, testCtrl.CreateGroup, authedRequest(t, "", "POST", "/", map[string]interface{}{ + "name": "shared bucket", + "members": []map[string]string{{"host": "Test1", "service": "containerTest1"}}, + })) + if status != http.StatusOK { + t.Fatalf("createGroup under DISABLE_AUTH returned %d: %s", status, body) + } + + status, body = call(t, testCtrl.GetGroups, authedRequest(t, "", "GET", "/", nil)) + if status != http.StatusOK || !slices.Contains(groupNames(t, body), "shared bucket") { + t.Fatalf("a second anonymous session did not see the group: %d %s", status, body) + } + + status, body = call(t, testCtrl.CreateGroup, authedRequest(t, "", "POST", "/", map[string]interface{}{ + "name": "shared bucket", + "members": []map[string]string{}, + })) + if status != http.StatusConflict { + t.Fatalf("a second anonymous createGroup returned %d, want 409: %s", status, body) + } +} + +func TestHostAliasIsAdminOnlyToSet(t *testing.T) { + t.Cleanup(func() { hostalias.Set("aliashost", "") }) + + status, body := call(t, testCtrl.SetHostAlias, + authedRequest(t, "viewer", "POST", "/", map[string]string{"host": "aliashost", "alias": "prod"})) + if status != http.StatusForbidden { + t.Fatalf("a non-admin set a host alias: status %d, %s", status, body) + } + if aliases, _ := hostalias.All(); aliases["aliashost"] != "" { + t.Fatalf("a non-admin's alias was stored: %q", aliases["aliashost"]) + } + + status, body = call(t, testCtrl.SetHostAlias, + authedRequest(t, "admin", "POST", "/", map[string]string{"host": "aliashost", "alias": "prod"})) + if status != http.StatusOK { + t.Fatalf("admin could not set a host alias: status %d, %s", status, body) + } + + status, body = call(t, testCtrl.GetHostAliases, authedRequest(t, "viewer", "GET", "/", nil)) + if status != http.StatusOK { + t.Fatalf("a normal user could not read host aliases: status %d, %s", status, body) + } + var aliases map[string]string + if err := json.Unmarshal(body, &aliases); err != nil { + t.Fatalf("unmarshalling aliases: %v -- %s", err, body) + } + if aliases["aliashost"] != "prod" { + t.Errorf("getHostAliases returned %v, want aliashost=prod", aliases) + } +} + +func TestHostAliasRejectsAnUnsafeHost(t *testing.T) { + status, _ := call(t, testCtrl.SetHostAlias, + authedRequest(t, "admin", "POST", "/", map[string]string{"host": "../../etc", "alias": "pwn"})) + if status != http.StatusBadRequest { + t.Fatalf("a traversing host was accepted: status %d", status) + } +} diff --git a/application/backend/app/routes/helpers_test.go b/application/backend/app/routes/helpers_test.go new file mode 100644 index 0000000..ae10821 --- /dev/null +++ b/application/backend/app/routes/helpers_test.go @@ -0,0 +1,45 @@ +package routes + +import ( + "bytes" + "encoding/json" + "io" + "net/http" + "net/http/httptest" + "testing" + + "github.com/devforth/OnLogs/app/util" +) + +// An empty user means no cookie at all, which is what an unauthenticated +// request and a DISABLE_AUTH request both look like. +func authedRequest(t *testing.T, user, method, target string, body any) *http.Request { + t.Helper() + + var reader io.Reader + if body != nil { + raw, err := json.Marshal(body) + if err != nil { + t.Fatalf("marshalling the request body: %v", err) + } + reader = bytes.NewReader(raw) + } + + req, err := http.NewRequest(method, target, reader) + if err != nil { + t.Fatalf("building the request: %v", err) + } + if user != "" { + req.AddCookie(&http.Cookie{Name: "onlogs-cookie", Value: util.CreateJWT(user)}) + } + return req +} + +func call(t *testing.T, handler http.HandlerFunc, req *http.Request) (int, []byte) { + t.Helper() + + rr := httptest.NewRecorder() + handler.ServeHTTP(rr, req) + body, _ := io.ReadAll(rr.Result().Body) + return rr.Result().StatusCode, body +} diff --git a/application/backend/app/routes/loginlimit.go b/application/backend/app/routes/loginlimit.go new file mode 100644 index 0000000..6365dc0 --- /dev/null +++ b/application/backend/app/routes/loginlimit.go @@ -0,0 +1,233 @@ +package routes + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "net" + "net/http" + "net/netip" + "strings" + "sync" + "time" +) + +const ( + freeLoginAttempts = 5 + maxLoginBackoff = 15 * time.Minute + loginAttemptTTL = time.Hour + maxLoginEntries = 4096 +) + +type loginAttempts struct { + mu sync.Mutex + entries map[string]*loginAttempt +} + +type loginAttempt struct { + failures int + blocked time.Time + seen time.Time +} + +var loginLimiter = &loginAttempts{entries: map[string]*loginAttempt{}} + +func backoffFor(failures int) time.Duration { + if failures <= freeLoginAttempts { + return 0 + } + backoff := time.Second << (failures - freeLoginAttempts - 1) + if backoff > maxLoginBackoff || backoff <= 0 { + return maxLoginBackoff + } + return backoff +} + +// Keys are bounded in size: the login half is attacker-chosen and can be up to +// the whole request body. +func loginKey(addr string, login string) string { + sum := sha256.Sum256([]byte(login)) + return addr + "|" + hex.EncodeToString(sum[:8]) +} + +func (l *loginAttempts) allow(keys ...string) bool { + now := time.Now() + + l.mu.Lock() + defer l.mu.Unlock() + + for _, key := range keys { + if entry, ok := l.entries[key]; ok && now.Before(entry.blocked) { + return false + } + } + return true +} + +func (l *loginAttempts) fail(keys ...string) { + now := time.Now() + + l.mu.Lock() + defer l.mu.Unlock() + l.prune(now) + + for _, key := range keys { + entry, ok := l.entries[key] + if !ok { + entry = &loginAttempt{} + l.entries[key] = entry + } + entry.failures++ + entry.seen = now + if backoff := backoffFor(entry.failures); backoff > 0 { + entry.blocked = now.Add(backoff) + } + } +} + +func (l *loginAttempts) succeed(keys ...string) { + l.mu.Lock() + defer l.mu.Unlock() + for _, key := range keys { + delete(l.entries, key) + } +} + +// Called only from fail(), so the scan cost is bounded by the failure rate +// rather than paid on every login. +func (l *loginAttempts) prune(now time.Time) { + for key, entry := range l.entries { + if now.Sub(entry.seen) > loginAttemptTTL && now.After(entry.blocked) { + delete(l.entries, key) + } + } + + if len(l.entries) < maxLoginEntries { + return + } + // Hard ceiling: drop everything that is not currently blocking anyone. + for key, entry := range l.entries { + if now.After(entry.blocked) { + delete(l.entries, key) + } + } +} + +// Empty means no peer may speak for anyone else. +var trustedProxies []netip.Prefix + +// SetTrustedProxies takes a comma separated list of IPs and CIDR ranges. +func SetTrustedProxies(spec string) error { + parsed, err := parseTrustedProxies(spec) + if err != nil { + return err + } + trustedProxies = parsed + return nil +} + +func parseTrustedProxies(spec string) ([]netip.Prefix, error) { + var parsed []netip.Prefix + for _, item := range strings.Split(spec, ",") { + item = strings.TrimSpace(item) + switch { + case item == "": + case strings.Contains(item, "/"): + prefix, err := netip.ParsePrefix(item) + if err != nil { + return nil, fmt.Errorf("%q is not a CIDR range: %w", item, err) + } + parsed = append(parsed, prefix.Masked()) + default: + addr, err := netip.ParseAddr(item) + if err != nil { + return nil, fmt.Errorf("%q is not an IP address or CIDR range: %w", item, err) + } + addr = addr.Unmap() + parsed = append(parsed, netip.PrefixFrom(addr, addr.BitLen())) + } + } + return parsed, nil +} + +func isTrustedProxy(addr netip.Addr) bool { + for _, prefix := range trustedProxies { + if prefix.Contains(addr) { + return true + } + } + return false +} + +// Zones and the IPv4-in-IPv6 form are dropped so one client cannot hold two +// buckets. +func parseIP(value string) (netip.Addr, bool) { + value = strings.TrimSpace(value) + if addr, err := netip.ParseAddr(value); err == nil { + return addr.Unmap().WithZone(""), true + } + if addrPort, err := netip.ParseAddrPort(value); err == nil { + return addrPort.Addr().Unmap().WithZone(""), true + } + return netip.Addr{}, false +} + +// The peer address, unless it is a trusted proxy: then the address it +// forwarded. The headers are caller-controlled, so taking them from anyone +// would let an attacker rotate past the limit or wear someone else's address. +func clientAddr(req *http.Request) string { + host, _, err := net.SplitHostPort(req.RemoteAddr) + if err != nil { + host = req.RemoteAddr + } + + peer, ok := parseIP(host) + if !ok { + return host + } + if !isTrustedProxy(peer) { + warnUntrustedForward(req) + return peer.String() + } + if forwarded, ok := forwardedClient(req); ok { + return forwarded + } + return peer.String() +} + +// Right to left: every hop appends the address it saw, so the rightmost entry +// no trusted proxy could have written is the last one still worth believing. +func forwardedClient(req *http.Request) (string, bool) { + entries := strings.Split(strings.Join(req.Header.Values("X-Forwarded-For"), ","), ",") + origin := "" + for i := len(entries) - 1; i >= 0; i-- { + addr, ok := parseIP(entries[i]) + if !ok { + break + } + if !isTrustedProxy(addr) { + return addr.String(), true + } + origin = addr.String() + } + + if addr, ok := parseIP(req.Header.Get("X-Real-IP")); ok { + return addr.String(), true + } + // Every hop was trusted, so the chain names its own origin. + return origin, origin != "" +} + +var forwardWarning sync.Once + +// Either a proxy nobody told us about, whose users then share one bucket, or +// someone trying on another address for size. +func warnUntrustedForward(req *http.Request) { + if req.Header.Get("X-Forwarded-For") == "" && req.Header.Get("X-Real-IP") == "" { + return + } + forwardWarning.Do(func() { + fmt.Printf("WARNING: a login from %s carried a forwarded client address, but that peer is not in TRUSTED_PROXIES;"+ + " rate limiting keys on the peer, so everyone behind it shares one limit.\n", req.RemoteAddr) + }) +} diff --git a/application/backend/app/routes/loginlimit_test.go b/application/backend/app/routes/loginlimit_test.go new file mode 100644 index 0000000..31f0b72 --- /dev/null +++ b/application/backend/app/routes/loginlimit_test.go @@ -0,0 +1,225 @@ +package routes + +import ( + "bytes" + "encoding/json" + "net/http" + "net/http/httptest" + "strconv" + "testing" + "time" + + "github.com/devforth/OnLogs/app/userdb" +) + +func TestLoginLimiterCannotBeUsedToLockOutAnAccount(t *testing.T) { + limiter := &loginAttempts{entries: map[string]*loginAttempt{}} + + attacker := "203.0.113.9" + victim := "198.51.100.7" + + // The attacker guesses at the admin account from their own address. + for i := 0; i < 50; i++ { + limiter.fail("ip:"+attacker, "pair:"+loginKey(attacker, "admin")) + } + + if limiter.allow("ip:" + attacker) { + t.Error("the attacker was not throttled") + } + if !limiter.allow("ip:"+victim, "pair:"+loginKey(victim, "admin")) { + t.Fatal("an attacker guessing at an account locked the real owner out of it") + } +} + +func TestLoginLimiterDoesNotGrowWithoutBound(t *testing.T) { + limiter := &loginAttempts{entries: map[string]*loginAttempt{}} + + // One failed attempt per distinct username, as an unauthenticated attacker + // can produce at will. + for i := 0; i < maxLoginEntries*3; i++ { + name := "user-" + strconv.Itoa(i) + limiter.fail("pair:" + loginKey("203.0.113.9", name)) + } + + limiter.mu.Lock() + size := len(limiter.entries) + limiter.mu.Unlock() + + if size > maxLoginEntries { + t.Fatalf("the limiter retained %d entries for %d attempts; memory grows without bound", + size, maxLoginEntries*3) + } +} + +func TestLoginLimiterKeysAreBounded(t *testing.T) { + huge := make([]byte, 900*1024) + for i := range huge { + huge[i] = 'a' + } + if got := len(loginKey("203.0.113.9", string(huge))); got > 64 { + t.Fatalf("a %d-byte login produced a %d-byte key", len(huge), got) + } +} + +func TestLoginLimiterStillThrottlesRepeatedFailures(t *testing.T) { + limiter := &loginAttempts{entries: map[string]*loginAttempt{}} + key := "pair:" + loginKey("203.0.113.9", "someone") + + for i := 0; i < freeLoginAttempts; i++ { + if !limiter.allow(key) { + t.Fatalf("throttled after only %d attempts", i) + } + limiter.fail(key) + } + limiter.fail(key) + + if limiter.allow(key) { + t.Fatal("repeated failures were not throttled") + } + if backoffFor(100) != maxLoginBackoff { + t.Errorf("backoff did not clamp: %v", backoffFor(100)) + } + if backoffFor(freeLoginAttempts) != 0 { + t.Errorf("throttled inside the free allowance: %v", backoffFor(freeLoginAttempts)) + } + _ = time.Second +} + +func withTrustedProxies(t *testing.T, spec string) { + t.Helper() + if err := SetTrustedProxies(spec); err != nil { + t.Fatalf("SetTrustedProxies(%q): %v", spec, err) + } + t.Cleanup(func() { trustedProxies = nil }) +} + +func forwardedRequest(peer string, headers map[string]string) *http.Request { + req, _ := http.NewRequest("POST", "/api/v1/login", nil) + req.RemoteAddr = peer + for name, value := range headers { + req.Header.Set(name, value) + } + return req +} + +func TestForwardedAddressesAreIgnoredFromUntrustedPeers(t *testing.T) { + req := forwardedRequest("203.0.113.9:40000", map[string]string{ + "X-Forwarded-For": "198.51.100.7", + "X-Real-IP": "198.51.100.7", + }) + + if got := clientAddr(req); got != "203.0.113.9" { + t.Fatalf("a caller wore another address with no proxy configured: %q", got) + } + + // Trusting some other proxy is not trusting this caller. + withTrustedProxies(t, "192.0.2.1,10.0.0.0/8") + if got := clientAddr(req); got != "203.0.113.9" { + t.Fatalf("a caller outside TRUSTED_PROXIES wore another address: %q", got) + } +} + +func TestClientAddrResolvesThroughTrustedProxies(t *testing.T) { + withTrustedProxies(t, "10.0.0.0/8,172.16.0.0/12") + + cases := []struct { + name string + peer string + headers map[string]string + want string + }{ + {"single hop", "10.0.0.1:40000", map[string]string{"X-Forwarded-For": "198.51.100.7"}, "198.51.100.7"}, + {"chained proxies", "10.0.0.1:40000", map[string]string{"X-Forwarded-For": "198.51.100.7, 10.0.0.5"}, "198.51.100.7"}, + {"client prepended a fake hop", "10.0.0.1:40000", map[string]string{"X-Forwarded-For": "1.1.1.1, 198.51.100.7"}, "198.51.100.7"}, + {"x-real-ip only", "10.0.0.1:40000", map[string]string{"X-Real-IP": "198.51.100.7"}, "198.51.100.7"}, + {"entry carries a port", "10.0.0.1:40000", map[string]string{"X-Forwarded-For": "198.51.100.7:1234"}, "198.51.100.7"}, + {"ipv4 in ipv6 form", "[::ffff:10.0.0.1]:40000", map[string]string{"X-Forwarded-For": "::ffff:198.51.100.7"}, "198.51.100.7"}, + {"unparseable chain", "10.0.0.1:40000", map[string]string{"X-Forwarded-For": "not-an-address"}, "10.0.0.1"}, + {"proxy forwarded nothing", "10.0.0.1:40000", nil, "10.0.0.1"}, + {"internal end to end", "10.0.0.1:40000", map[string]string{"X-Forwarded-For": "10.9.9.9, 10.0.0.5"}, "10.9.9.9"}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + if got := clientAddr(forwardedRequest(tc.peer, tc.headers)); got != tc.want { + t.Fatalf("got %q, want %q", got, tc.want) + } + }) + } +} + +func TestTrustedProxySpecIsValidated(t *testing.T) { + if _, err := parseTrustedProxies(" 10.0.0.0/8 , 192.0.2.1,::1 "); err != nil { + t.Fatalf("a valid spec was rejected: %v", err) + } + if parsed, err := parseTrustedProxies(""); err != nil || parsed != nil { + t.Fatalf("an empty spec gave (%v, %v)", parsed, err) + } + for _, spec := range []string{"10.0.0.0/99", "not-an-address", "10.0.0.1-10.0.0.5", "10.0.0.0/8,junk"} { + if _, err := parseTrustedProxies(spec); err == nil { + t.Errorf("%q was accepted", spec) + } + } +} + +// The lockout lived in which key the handler chose, so it has to be exercised +// through the handler. +func TestLoginLockoutCannotBeInflictedOnAnotherUser(t *testing.T) { + userdb.CreateUser("victimaccount", "the-real-password") + t.Cleanup(func() { userdb.DeleteUser("victimaccount") }) + + loginLimiter.mu.Lock() + loginLimiter.entries = map[string]*loginAttempt{} + loginLimiter.mu.Unlock() + + attempt := func(addr, password string) int { + body, _ := json.Marshal(map[string]string{"Login": "victimaccount", "Password": password}) + req, _ := http.NewRequest("POST", "/api/v1/login", bytes.NewBuffer(body)) + req.RemoteAddr = addr + ":40000" + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.Login).ServeHTTP(rr, req) + return rr.Result().StatusCode + } + + // An attacker guesses at the account from their own address. + for i := 0; i < 20; i++ { + attempt("203.0.113.9", "guess-"+strconv.Itoa(i)) + } + if code := attempt("203.0.113.9", "the-real-password"); code != http.StatusTooManyRequests { + t.Errorf("the attacker was not throttled: status %d", code) + } + + if code := attempt("198.51.100.7", "the-real-password"); code != http.StatusOK { + t.Fatalf("an attacker guessing at the account locked its real owner out: status %d", code) + } +} + +func TestOneAttackerBehindAProxyDoesNotThrottleEveryoneElse(t *testing.T) { + userdb.CreateUser("proxieduser", "the-real-password") + t.Cleanup(func() { userdb.DeleteUser("proxieduser") }) + withTrustedProxies(t, "10.0.0.0/8,172.16.0.0/12") + + loginLimiter.mu.Lock() + loginLimiter.entries = map[string]*loginAttempt{} + loginLimiter.mu.Unlock() + + attempt := func(client, password string) int { + body, _ := json.Marshal(map[string]string{"Login": "proxieduser", "Password": password}) + req, _ := http.NewRequest("POST", "/api/v1/login", bytes.NewBuffer(body)) + req.RemoteAddr = "172.18.0.2:40000" + req.Header.Set("X-Forwarded-For", client) + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.Login).ServeHTTP(rr, req) + return rr.Result().StatusCode + } + + for i := 0; i < 20; i++ { + attempt("203.0.113.9", "guess-"+strconv.Itoa(i)) + } + if code := attempt("203.0.113.9", "the-real-password"); code != http.StatusTooManyRequests { + t.Errorf("the attacker was not throttled through the proxy: status %d", code) + } + if code := attempt("198.51.100.7", "the-real-password"); code != http.StatusOK { + t.Fatalf("one attacker behind the proxy locked out everyone else: status %d", code) + } +} diff --git a/application/backend/app/routes/routes.go b/application/backend/app/routes/routes.go index dcce55a..c8f7f57 100644 --- a/application/backend/app/routes/routes.go +++ b/application/backend/app/routes/routes.go @@ -2,13 +2,16 @@ package routes import ( "bytes" + "context" "encoding/json" "fmt" "io" "mime" "net/http" + "net/url" "os" "path/filepath" + "slices" "strconv" "strings" "time" @@ -17,6 +20,8 @@ import ( "github.com/devforth/OnLogs/app/daemon" "github.com/devforth/OnLogs/app/db" "github.com/devforth/OnLogs/app/docker" + "github.com/devforth/OnLogs/app/groups" + "github.com/devforth/OnLogs/app/hostalias" "github.com/devforth/OnLogs/app/statistics" "github.com/devforth/OnLogs/app/userdb" "github.com/devforth/OnLogs/app/util" @@ -25,79 +30,146 @@ import ( ) type RouteController struct { - DockerService *docker.DockerService - DaemonService *daemon.DaemonService + DockerService *docker.DockerService + DaemonService *daemon.DaemonService } -func enableCors(w *http.ResponseWriter) { +func enableCors(w http.ResponseWriter) { var origin string if os.Getenv("ENV_NAME") == "local" { origin = "http://localhost:5173" - } else { - origin = "" } - (*w).Header().Set("Access-Control-Allow-Origin", origin) - (*w).Header().Set("Access-Control-Allow-Credentials", "true") - (*w).Header().Set("Access-Control-Allow-Methods", "*") - (*w).Header().Set("Access-Control-Allow-Headers", "Content-Type") + w.Header().Set("Access-Control-Allow-Origin", origin) + w.Header().Set("Access-Control-Allow-Credentials", "true") + w.Header().Set("Access-Control-Allow-Methods", "*") + w.Header().Set("Access-Control-Allow-Headers", "Content-Type") } -func verifyAdminUser(w *http.ResponseWriter, req *http.Request) bool { +func isAllowedOrigin(req *http.Request) bool { + origin := req.Header.Get("Origin") + if origin == "" { + return true + } + parsed, err := url.Parse(origin) + if err != nil { + return false + } + if os.Getenv("ENV_NAME") == "local" && parsed.Host == "localhost:5173" { + return true + } + return strings.EqualFold(parsed.Host, req.Host) +} + +func verifyAdminUser(w http.ResponseWriter, req *http.Request) bool { if os.Getenv("DISABLE_AUTH") == "true" { return true } username, err := util.GetUserFromJWT(*req) if username != os.Getenv("ADMIN_USERNAME") { - (*w).WriteHeader(http.StatusForbidden) - json.NewEncoder(*w).Encode(map[string]string{"error": "Only admin can perform this request"}) + fail(w, http.StatusForbidden, "Only admin can perform this request") return false } if err != nil { - (*w).WriteHeader(http.StatusUnauthorized) - json.NewEncoder(*w).Encode(map[string]string{"error": err.Error()}) + fail(w, http.StatusUnauthorized, err.Error()) return false } return true } -func verifyUser(w *http.ResponseWriter, req *http.Request) bool { +func verifyUser(w http.ResponseWriter, req *http.Request) bool { if os.Getenv("DISABLE_AUTH") == "true" { return true } - _, err := util.GetUserFromJWT(*req) - if err != nil { - (*w).WriteHeader(http.StatusUnauthorized) - json.NewEncoder(*w).Encode(map[string]string{"error": err.Error()}) + if _, err := util.GetUserFromJWT(*req); err != nil { + fail(w, http.StatusUnauthorized, err.Error()) return false } return true } -func verifyRequest(w *http.ResponseWriter, req *http.Request) bool { +type authLevel int + +const ( + authNone authLevel = iota + authUser + authAdmin +) + +// False means the request must not reach the handler body: a CORS preflight, a +// rejected credential, or the wrong method. An empty method accepts any. +func guard(w http.ResponseWriter, req *http.Request, level authLevel, method string) bool { enableCors(w) - if req.Method == "OPTIONS" { - (*w).WriteHeader(http.StatusOK) - return true + if req.Method == http.MethodOptions { + w.WriteHeader(http.StatusOK) + return false } - return false + + switch level { + case authUser: + if !verifyUser(w, req) { + return false + } + case authAdmin: + if !verifyAdminUser(w, req) { + return false + } + } + + if method != "" && req.Method != method { + w.WriteHeader(http.StatusNotFound) + return false + } + return true } -func (h *RouteController)Frontend(w http.ResponseWriter, req *http.Request) { - requestedPath := strings.ReplaceAll(req.URL.String(), os.Getenv("ONLOGS_PATH_PREFIX"), "") +func writeJSON(w http.ResponseWriter, status int, payload any) { + w.Header().Set("Content-Type", "application/json") + if status != http.StatusOK { + w.WriteHeader(status) + } + json.NewEncoder(w).Encode(payload) +} + +func ok(w http.ResponseWriter) { + writeJSON(w, http.StatusOK, map[string]any{"error": nil}) +} - dirPath, fileName := filepath.Split(requestedPath) - if fileName == "" { +func fail(w http.ResponseWriter, status int, message string) { + writeJSON(w, status, map[string]string{"error": message}) +} + +const ( + maxRequestBody = 1 << 20 + sessionLifetime = 48 * time.Hour +) + +func isTLS(req *http.Request) bool { + return req.TLS != nil || strings.EqualFold(req.Header.Get("X-Forwarded-Proto"), "https") +} + +func decodeBody(w http.ResponseWriter, req *http.Request, target interface{}) bool { + req.Body = http.MaxBytesReader(w, req.Body, maxRequestBody) + if err := json.NewDecoder(req.Body).Decode(target); err != nil { + fail(w, http.StatusBadRequest, "Invalid request body") + return false + } + return true +} + +func (h *RouteController) Frontend(w http.ResponseWriter, req *http.Request) { + // http.Dir sanitises the name it is given but never its own root. + dir := http.Dir("dist") + + fileName := strings.TrimPrefix(strings.TrimPrefix(req.URL.Path, os.Getenv("ONLOGS_PATH_PREFIX")), "/") + if fileName == "" || strings.HasSuffix(fileName, "/") { fileName = "index.html" } - fileName = strings.Split(fileName, "?")[0] - dir := http.Dir("dist" + dirPath) file, err := dir.Open(fileName) if err != nil { - dir = http.Dir("dist") file, err = dir.Open("index.html") fileName = "index.html" } @@ -125,32 +197,35 @@ func (h *RouteController)Frontend(w http.ResponseWriter, req *http.Request) { http.ServeContent(w, req, fileName, stat.ModTime(), bytes.NewReader(content)) } -func (h *RouteController)CheckCookie(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) CheckCookie(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"error": nil}) + ok(w) } -func (h *RouteController)AddLogLine(w http.ResponseWriter, req *http.Request) { +func (h *RouteController) AddLogLine(w http.ResponseWriter, req *http.Request) { var logItem struct { Token string Host string Container string LogLine []string } - decoder := json.NewDecoder(req.Body) - decoder.Decode(&logItem) + if !decodeBody(w, req, &logItem) { + return + } if !db.IsTokenExists(logItem.Token) { w.WriteHeader(http.StatusUnauthorized) return } - if vars.Counters_For_Hosts_Last_30_Min[logItem.Host] == nil { - go statistics.RunStatisticForContainer(logItem.Host, logItem.Container) + if !util.IsSafeName(logItem.Host) || !util.IsSafeName(logItem.Container) || len(logItem.LogLine) < 2 { + w.WriteHeader(http.StatusBadRequest) + return } + + statistics.EnsureWorker(context.Background(), logItem.Host, logItem.Container) err := containerdb.PutLogMessage(util.GetDB(logItem.Host, logItem.Container, "logs"), logItem.Host, logItem.Container, logItem.LogLine) if err != nil { defer w.WriteHeader(http.StatusInternalServerError) @@ -158,14 +233,10 @@ func (h *RouteController)AddLogLine(w http.ResponseWriter, req *http.Request) { } to_send, _ := json.Marshal([]string{logItem.LogLine[0], logItem.LogLine[1]}) - conns := vars.Connections[logItem.Host+"/"+logItem.Container] - for i := range conns { - c := conns[i] - c.WriteMessage(websocket.TextMessage, to_send) - } + vars.Broadcast(logItem.Host+"/"+logItem.Container, websocket.TextMessage, to_send) } -func (h *RouteController)AddHost(w http.ResponseWriter, req *http.Request) { +func (h *RouteController) AddHost(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { w.WriteHeader(http.StatusNotFound) return @@ -176,28 +247,35 @@ func (h *RouteController)AddHost(w http.ResponseWriter, req *http.Request) { Token string Services []string } - decoder := json.NewDecoder(req.Body) - decoder.Decode(&addReq) + if !decodeBody(w, req, &addReq) { + return + } if !db.IsTokenExists(addReq.Token) { w.WriteHeader(http.StatusUnauthorized) return } - vars.AgentsActiveContainers[addReq.Hostname] = addReq.Services + if !util.IsSafeName(addReq.Hostname) { + w.WriteHeader(http.StatusBadRequest) + return + } + for _, container := range addReq.Services { + if !util.IsSafeName(container) { + w.WriteHeader(http.StatusBadRequest) + return + } + } + + vars.SetAgentContainers(addReq.Hostname, addReq.Services) // fmt.Println("New host added: " + addReq.Hostname) need to create separate route for SendUpdate func for _, container := range addReq.Services { os.MkdirAll("leveldb/hosts/"+addReq.Hostname+"/containers/"+container, 0700) } } -func (h *RouteController)ChangeFavourite(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { - return - } - - if req.Method != "POST" { - w.WriteHeader(http.StatusNotFound) +func (h *RouteController) ChangeFavourite(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "POST") { return } @@ -205,37 +283,224 @@ func (h *RouteController)ChangeFavourite(w http.ResponseWriter, req *http.Reques Host string `json:"host"` Service string `json:"service"` } - decoder := json.NewDecoder(req.Body) - decoder.Decode(&container) + if !decodeBody(w, req, &container) { + return + } - key := []byte(container.Host + "/" + container.Service) - isAlreadyFavourite, _ := vars.FavsDB.Has(key, nil) - if isAlreadyFavourite { - vars.FavsDB.Delete(key, nil) - } else { - vars.FavsDB.Put(key, nil, nil) + username, _ := util.GetUserFromJWT(*req) + key := favouriteKey(username, container.Host, container.Service) + + isAlreadyFavourite, err := vars.FavsDB.Has(key, nil) + if err == nil { + if isAlreadyFavourite { + err = vars.FavsDB.Delete(key, nil) + } else { + err = vars.FavsDB.Put(key, nil, nil) + } } - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"error": nil}) + if err != nil { + fail(w, http.StatusInternalServerError, err.Error()) + return + } + ok(w) } -func (h *RouteController)GetSecret(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) GetGroups(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]string{"token": db.CreateOnLogsToken()}) + username, _ := util.GetUserFromJWT(*req) + list, err := groups.List(username) + + if err != nil { + fail(w, http.StatusInternalServerError, err.Error()) + return + } + writeJSON(w, http.StatusOK, list) } -func (h *RouteController)GetChartData(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) CreateGroup(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "POST") { return } - if req.Method != "POST" { - w.WriteHeader(http.StatusNotFound) + var body struct { + Name string `json:"name"` + Members []groups.Member `json:"members"` + } + if !decodeBody(w, req, &body) { + return + } + + if err := groups.ValidateGroupName(body.Name); err != nil { + fail(w, http.StatusBadRequest, err.Error()) + return + } + if err := groups.ValidateMembers(body.Members); err != nil { + fail(w, http.StatusBadRequest, err.Error()) + return + } + + username, _ := util.GetUserFromJWT(*req) + existing, err := groups.List(username) + if err != nil { + fail(w, http.StatusInternalServerError, err.Error()) + return + } + for _, group := range existing { + if group.Name == body.Name { + fail(w, http.StatusConflict, "Group \""+body.Name+"\" already exists") + return + } + } + // An authenticated user must not be able to write unbounded data to LevelDB. + if len(existing) >= groups.MaxGroupsPerUser { + fail(w, http.StatusBadRequest, + fmt.Sprintf("You can not have more than %d groups", groups.MaxGroupsPerUser)) + return + } + + if err := groups.Store(username, body.Name, body.Members); err != nil { + fail(w, http.StatusInternalServerError, err.Error()) + return + } + ok(w) +} + +func (h *RouteController) UpdateGroup(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "POST") { + return + } + + var body struct { + Name string `json:"name"` + NewName string `json:"newName"` + Members []groups.Member `json:"members"` + } + if !decodeBody(w, req, &body) { + return + } + + newName := body.NewName + if newName == "" { + newName = body.Name + } + + if err := groups.ValidateGroupName(body.Name); err != nil { + fail(w, http.StatusBadRequest, err.Error()) + return + } + if err := groups.ValidateGroupName(newName); err != nil { + fail(w, http.StatusBadRequest, err.Error()) + return + } + if err := groups.ValidateMembers(body.Members); err != nil { + fail(w, http.StatusBadRequest, err.Error()) + return + } + + username, _ := util.GetUserFromJWT(*req) + _, found, err := groups.Load(username, body.Name) + if err != nil { + fail(w, http.StatusInternalServerError, err.Error()) + return + } + if !found { + fail(w, http.StatusNotFound, "No such group") + return + } + + if newName != body.Name { + if _, taken, _ := groups.Load(username, newName); taken { + fail(w, http.StatusConflict, "Group \""+newName+"\" already exists") + return + } + } + + if err := groups.Store(username, newName, body.Members); err != nil { + fail(w, http.StatusInternalServerError, err.Error()) + return + } + if newName != body.Name { + if err := groups.Delete(username, body.Name); err != nil { + fail(w, http.StatusInternalServerError, err.Error()) + return + } + } + ok(w) +} + +func (h *RouteController) DeleteGroup(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "POST") { + return + } + + var body struct { + Name string `json:"name"` + } + if !decodeBody(w, req, &body) { + return + } + + if err := groups.ValidateGroupName(body.Name); err != nil { + fail(w, http.StatusBadRequest, err.Error()) + return + } + + username, _ := util.GetUserFromJWT(*req) + // Deleting what is not there is a success, because the UI may double-fire. + if err := groups.Delete(username, body.Name); err != nil { + fail(w, http.StatusInternalServerError, err.Error()) + return + } + ok(w) +} + +func (h *RouteController) GetHostAliases(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { + return + } + + aliases, err := hostalias.All() + if err != nil { + fail(w, http.StatusInternalServerError, err.Error()) + return + } + writeJSON(w, http.StatusOK, aliases) +} + +func (h *RouteController) SetHostAlias(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authAdmin, "POST") { + return + } + + var body struct { + Host string `json:"host"` + Alias string `json:"alias"` + } + if !decodeBody(w, req, &body) { + return + } + + if err := hostalias.Set(body.Host, body.Alias); err != nil { + fail(w, http.StatusBadRequest, err.Error()) + return + } + ok(w) +} + +func (h *RouteController) GetSecret(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authAdmin, "") { + return + } + + writeJSON(w, http.StatusOK, map[string]string{"token": db.CreateOnLogsToken()}) +} + +func (h *RouteController) GetChartData(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "POST") { return } @@ -245,29 +510,21 @@ func (h *RouteController)GetChartData(w http.ResponseWriter, req *http.Request) Unit string `json:"unit"` UnitsAmount int `json:"unitsAmount"` } - decoder := json.NewDecoder(req.Body) - err := decoder.Decode(&data) - if err != nil { - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"error": "Invalid data!"}) + if !decodeBody(w, req, &data) { return } - if !util.Contains(data.Unit, []string{"hour", "day", "month"}) { - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"error": "Invalid data!"}) + if !slices.Contains([]string{"hour", "day", "month"}, data.Unit) { + w.WriteHeader(http.StatusBadRequest) + writeJSON(w, http.StatusOK, map[string]interface{}{"error": "Invalid data!"}) + return } - w.Header().Add("Content-Type", "application/json") - e, _ := json.Marshal( - statistics.GetChartData( - data.Host, data.Service, data.Unit, data.UnitsAmount, - )) - w.Write(e) + writeJSON(w, http.StatusOK, statistics.GetChartData(data.Host, data.Service, data.Unit, data.UnitsAmount)) } func (h *RouteController) GetHosts(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { + if !guard(w, req, authUser, "") { return } @@ -276,7 +533,8 @@ func (h *RouteController) GetHosts(w http.ResponseWriter, req *http.Request) { Services []map[string]interface{} `json:"services"` } - var to_return []HostsList + to_return := []HostsList{} + viewer, _ := util.GetUserFromJWT(*req) ctx := req.Context() activeContainers := h.DaemonService.GetContainersList(ctx) @@ -285,8 +543,8 @@ func (h *RouteController) GetHosts(w http.ResponseWriter, req *http.Request) { containers, _ := os.ReadDir("leveldb/hosts/" + host.Name() + "/containers") allContainers := []map[string]interface{}{} for _, container := range containers { - isFavorite, _ := vars.FavsDB.Has([]byte(util.GetHost()+"/"+container.Name()), nil) - if util.Contains(container.Name(), activeContainers) || util.Contains(container.Name(), vars.AgentsActiveContainers[host.Name()]) { + isFavorite, _ := vars.FavsDB.Has(favouriteKey(viewer, host.Name(), container.Name()), nil) + if slices.Contains(activeContainers, container.Name()) || slices.Contains(vars.AgentContainers(host.Name()), container.Name()) { allContainers = append(allContainers, map[string]interface{}{"serviceName": container.Name(), "isDisabled": false, "isFavorite": isFavorite}) } else { allContainers = append(allContainers, map[string]interface{}{"serviceName": container.Name(), "isDisabled": true, "isFavorite": isFavorite}) @@ -295,35 +553,26 @@ func (h *RouteController) GetHosts(w http.ResponseWriter, req *http.Request) { to_return = append(to_return, HostsList{Host: host.Name(), Services: allContainers}) } - w.Header().Add("Content-Type", "application/json") - e, _ := json.Marshal(to_return) - w.Write(e) + writeJSON(w, http.StatusOK, to_return) } -func (h *RouteController)GetSizeByAll(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) GetSizeByAll(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } - var totalSize float64 - hosts, _ := os.ReadDir("leveldb/hosts/") - for _, host := range hosts { - containers, _ := os.ReadDir("leveldb/hosts/" + host.Name() + "/containers") - for _, container := range containers { - totalSize += util.GetDirSize(host.Name(), container.Name()) - } - } + _, totalBytes := util.LogsSizes() + totalSize := float64(totalBytes) / (1024.0 * 1024.0) if totalSize < 0.1 && totalSize != 0.0 { totalSize = 0.1 } - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"sizeMiB": fmt.Sprintf("%.1f", totalSize)}) // MiB + writeJSON(w, http.StatusOK, map[string]interface{}{"sizeMiB": fmt.Sprintf("%.1f", totalSize)}) // MiB } // TODO need to return 0.0 when there is no logs for container in db -func (h *RouteController)GetSizeByService(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) GetSizeByService(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } @@ -336,17 +585,16 @@ func (h *RouteController)GetSizeByService(w http.ResponseWriter, req *http.Reque if params.Get("host") == "" { panic("Host is not mentioned!") } - w.Header().Add("Content-Type", "application/json") size := util.GetDirSize(params.Get("host"), params.Get("service")) if size < 0.1 && size != 0.0 { size = 0.1 } - json.NewEncoder(w).Encode(map[string]interface{}{"sizeMiB": fmt.Sprintf("%.1f", size)}) // MiB + writeJSON(w, http.StatusOK, map[string]interface{}{"sizeMiB": fmt.Sprintf("%.1f", size)}) // MiB } -func (h *RouteController)GetDockerSize(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) GetDockerSize(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } @@ -357,22 +605,27 @@ func (h *RouteController)GetDockerSize(w http.ResponseWriter, req *http.Request) } if params.Get("host") == "" { - panic("Host is not mentioned!") + fail(w, http.StatusBadRequest, "Host is not mentioned!") + return } - w.Header().Add("Content-Type", "application/json") + // A container with no docker json log has size 0, not a nil dereference. + var size float64 containerID := util.GetDockerContainerID(params.Get("host"), params.Get("service")) - info, _ := os.Stat("/var/lib/docker/containers/" + containerID + "/" + containerID + "-json.log") + if containerID != "" { + if info, err := os.Stat("/var/lib/docker/containers/" + containerID + "/" + containerID + "-json.log"); err == nil && info != nil { + size = float64(info.Size()) / (1024.0 * 1024.0) + } + } - size := float64(info.Size()) / (1024.0 * 1024.0) if size < 0.1 && size != 0.0 { size = 0.1 } - json.NewEncoder(w).Encode(map[string]interface{}{"sizeMiB": fmt.Sprintf("%.1f", size)}) // MiB + writeJSON(w, http.StatusOK, map[string]interface{}{"sizeMiB": fmt.Sprintf("%.1f", size)}) // MiB } -func (h *RouteController)GetStats(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) GetStats(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } @@ -382,20 +635,14 @@ func (h *RouteController)GetStats(w http.ResponseWriter, req *http.Request) { Value int `json:"period"` // 1 = 30min, 2 = 1hr, 48 = 1d } - decoder := json.NewDecoder(req.Body) - err := decoder.Decode(&data) - - if err != nil { - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]string{"error": "Invalid data!"}) + if !decodeBody(w, req, &data) { return } - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(statistics.GetStatisticsByService(data.Host, data.Service, data.Value)) + writeJSON(w, http.StatusOK, statistics.GetStatisticsByService(data.Host, data.Service, data.Value)) } -func (h *RouteController)GetStorageData(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) GetStorageData(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } @@ -403,25 +650,33 @@ func (h *RouteController)GetStorageData(w http.ResponseWriter, req *http.Request Host string `json:"host"` } - decoder := json.NewDecoder(req.Body) - err := decoder.Decode(&data) - - w.Header().Add("Content-Type", "application/json") - if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": "Invalid data!"}) + if !decodeBody(w, req, &data) { return } // TODO make for different hosts if data.Host != util.GetHost() { - json.NewEncoder(w).Encode(map[string]string{"error": "For now working only for main host.\nAsked host: " + data.Host + "\nIt's ok to see this message, all works fine."}) + fail(w, http.StatusOK, "For now working only for main host.\nAsked host: "+data.Host+"\nIt's ok to see this message, all works fine.") return } - json.NewEncoder(w).Encode(util.GetStorageData()) + writeJSON(w, http.StatusOK, util.GetStorageData()) +} + +// Favourites are per user, like the user settings stored next to them. +func favouriteKey(username string, host string, service string) []byte { + return []byte(username + "\x00" + host + "/" + service) +} + +func statusFilter(params url.Values) *string { + status := params.Get("status") + if status == "" { + return nil + } + return &status } -func (h *RouteController)GetPrevLogs(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) GetPrevLogs(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } @@ -433,19 +688,18 @@ func (h *RouteController)GetPrevLogs(w http.ResponseWriter, req *http.Request) { } if params.Get("startWith") == "" { - json.NewEncoder(w).Encode(map[string]interface{}{"error": "Need to specify \"startWith\"!"}) + writeJSON(w, http.StatusOK, map[string]interface{}{"error": "Need to specify \"startWith\"!"}) return } - w.Header().Add("Content-Type", "application/json") if params.Get("host") == "" { panic("Host is not mentioned!") } - json.NewEncoder(w).Encode(containerdb.GetLogs(true, false, params.Get("host"), params.Get("id"), params.Get("search"), limit, params.Get("startWith"), caseSensetive, nil)) + writeJSON(w, http.StatusOK, containerdb.GetLogs(true, false, params.Get("host"), params.Get("id"), params.Get("search"), limit, params.Get("startWith"), caseSensetive, statusFilter(params))) } -func (h *RouteController)GetLogs(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) GetLogs(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } @@ -455,40 +709,32 @@ func (h *RouteController)GetLogs(w http.ResponseWriter, req *http.Request) { if err != nil { caseSensetive = false } - w.Header().Add("Content-Type", "application/json") if params.Get("host") == "" { panic("Host is not mentioned!") } - status := params.Get("status") - var statusPtr *string - if status != "" { - statusPtr = &status - } - - json.NewEncoder(w).Encode(containerdb.GetLogs( + writeJSON(w, http.StatusOK, containerdb.GetLogs( false, false, params.Get("host"), params.Get("id"), params.Get("search"), - limit, params.Get("startWith"), caseSensetive, statusPtr, + limit, params.Get("startWith"), caseSensetive, statusFilter(params), )) } -func (h *RouteController)GetLogWithPrev(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) GetLogWithPrev(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } params := req.URL.Query() limit, _ := strconv.Atoi(params.Get("limit")) - w.Header().Add("Content-Type", "application/json") if params.Get("host") == "" { panic("Host is not mentioned!") } - json.NewEncoder(w).Encode(containerdb.GetLogs(false, true, params.Get("host"), params.Get("id"), "", limit, params.Get("startWith"), false, nil)) + writeJSON(w, http.StatusOK, containerdb.GetLogs(false, true, params.Get("host"), params.Get("id"), "", limit, params.Get("startWith"), false, statusFilter(params))) } // TODO return {"error": "Invalid host!"} when host is not exists -func (h *RouteController)GetLogsStream(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) GetLogsStream(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } @@ -509,171 +755,174 @@ func (h *RouteController)GetLogsStream(w http.ResponseWriter, req *http.Request) var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, + CheckOrigin: isAllowedOrigin, } - upgrader.CheckOrigin = func(r *http.Request) bool { return true } // verify req here? ws, err := upgrader.Upgrade(w, req, nil) if err != nil { + // gorilla returns (nil, err); appending here seeds a nil conn that a + // background goroutine later dereferences. fmt.Println(err) + return } - vars.Connections[container] = append(vars.Connections[container], ws) + vars.AddConnection(container, ws) } -func (h *RouteController)Login(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) { - json.NewEncoder(w).Encode(map[string]interface{}{"error": nil}) +func (h *RouteController) Login(w http.ResponseWriter, req *http.Request) { + enableCors(w) + if req.Method == http.MethodOptions { + ok(w) return } - if req.Method != "POST" { w.WriteHeader(http.StatusNotFound) return } var loginData vars.UserData - decoder := json.NewDecoder(req.Body) - decoder.Decode(&loginData) + if !decodeBody(w, req, &loginData) { + return + } + + // Keyed on the address and on the (address, login) pair -- never on the login + // alone, or anyone could lock any account out by guessing at it. + addr := clientAddr(req) + ipKey := "ip:" + addr + pairKey := "pair:" + loginKey(addr, loginData.Login) + if !loginLimiter.allow(ipKey, pairKey) { + vars.LoginBlocked.Add(1) + fail(w, http.StatusTooManyRequests, "Too many failed login attempts. Try again later.") + return + } isCorrect := userdb.CheckUserPassword(loginData.Login, loginData.Password) if !isCorrect { - json.NewEncoder(w).Encode(map[string]string{"error": "Wrong login or password!"}) + // Once per request, not once per key: fail() takes two. + vars.LoginFailures.Add(1) + loginLimiter.fail(ipKey, pairKey) + fail(w, http.StatusOK, "Wrong login or password!") return } + loginLimiter.succeed(ipKey, pairKey) http.SetCookie(w, &http.Cookie{ Name: "onlogs-cookie", Value: util.CreateJWT(loginData.Login), Expires: time.Now().AddDate(0, 0, 2), - MaxAge: int(time.Now().AddDate(0, 0, 2).Unix()), + MaxAge: int(sessionLifetime / time.Second), + HttpOnly: true, + Secure: isTLS(req), SameSite: http.SameSiteLaxMode, Path: "/", }) - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"error": nil}) + ok(w) } -func (h *RouteController)Logout(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) Logout(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } http.SetCookie(w, &http.Cookie{ Name: "onlogs-cookie", Value: "toDelete", Expires: time.Now().AddDate(-5, -5, -5), - MaxAge: 0, + MaxAge: -1, + HttpOnly: true, + Secure: isTLS(req), SameSite: http.SameSiteLaxMode, Path: "/", }) - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"error": nil}) + ok(w) } -func (h *RouteController)CreateUser(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyAdminUser(&w, req) { +func (h *RouteController) CreateUser(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authAdmin, "POST") { return } - if req.Method != "POST" { - w.WriteHeader(http.StatusNotFound) + var loginData vars.UserData + if !decodeBody(w, req, &loginData) { return } - var loginData vars.UserData - decoder := json.NewDecoder(req.Body) - decoder.Decode(&loginData) - err := userdb.CreateUser(loginData.Login, loginData.Password) if err == nil { - json.NewEncoder(w).Encode(map[string]interface{}{"error": nil}) + ok(w) return } - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + fail(w, http.StatusOK, err.Error()) } -func (h *RouteController)GetUsers(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) GetUsers(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authAdmin, "") { return } users := userdb.GetUsers() - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"users": users, "error": nil}) + writeJSON(w, http.StatusOK, map[string]interface{}{"users": users, "error": nil}) } -func (h *RouteController)UpdateUserSettings(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) UpdateUserSettings(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } var settings map[string]interface{} - body, _ := io.ReadAll(req.Body) - json.Unmarshal(body, &settings) + if !decodeBody(w, req, &settings) { + return + } username, _ := util.GetUserFromJWT(*req) - userdb.UpdateUserSettings(username, settings) - json.NewEncoder(w).Encode(map[string]interface{}{"error": nil}) + if err := userdb.UpdateUserSettings(username, settings); err != nil { + fail(w, http.StatusInternalServerError, err.Error()) + return + } + ok(w) } -func (h *RouteController)GetUserSettings(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyUser(&w, req) { +func (h *RouteController) GetUserSettings(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authUser, "") { return } username, _ := util.GetUserFromJWT(*req) - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(userdb.GetUserSettings(username)) + writeJSON(w, http.StatusOK, userdb.GetUserSettings(username)) } -func (h *RouteController)EditHostname(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyAdminUser(&w, req) { +func (h *RouteController) EditUser(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authAdmin, "") { return } - var data struct { - Host string - Name string + var loginData vars.UserData + if !decodeBody(w, req, &loginData) { + return } - decoder := json.NewDecoder(req.Body) - decoder.Decode(&data) - if data.Name != "" { - if data.Host != util.GetHost() { - // TODO ask for command - } else { - os.WriteFile("/etc/hosntame", []byte(data.Name), 0644) - } + if loginData.Login == os.Getenv("ADMIN_USERNAME") { + fail(w, http.StatusOK, "Can't edit admin. Use env variables to change admin username and password") + return } - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"error": nil}) -} - -func (h *RouteController)EditUser(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyAdminUser(&w, req) { + if !userdb.IsUserExists(loginData.Login) { + fail(w, http.StatusOK, "No such user") return } - var loginData vars.UserData - decoder := json.NewDecoder(req.Body) - decoder.Decode(&loginData) - - if loginData.Login == os.Getenv("ADMIN_USERNAME") { - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]string{"error": "Can't edit admin. Use env variables to change admin username and password"}) + if loginData.Password == "" { + fail(w, http.StatusOK, "Password can not be empty") return } - if !userdb.IsUserExists(loginData.Login) { - json.NewEncoder(w).Encode(map[string]string{"error": "No such user"}) + if err := userdb.EditUser(loginData.Login, loginData.Password); err != nil { + fail(w, http.StatusOK, err.Error()) return } - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"error": nil}) + ok(w) } -func (h *RouteController)DeleteContainerLogs(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyAdminUser(&w, req) { +func (h *RouteController) DeleteContainerLogs(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authAdmin, "") { return } @@ -681,16 +930,16 @@ func (h *RouteController)DeleteContainerLogs(w http.ResponseWriter, req *http.Re Host string `json:"host"` Service string `json:"service"` } - decoder := json.NewDecoder(req.Body) - decoder.Decode(&containerItem) + if !decodeBody(w, req, &containerItem) { + return + } go containerdb.DeleteContainer(containerItem.Host, containerItem.Service, false) - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"error": nil}) + ok(w) } -func (h *RouteController)DeleteDockerLogs(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyAdminUser(&w, req) { +func (h *RouteController) DeleteDockerLogs(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authAdmin, "") { return } @@ -698,38 +947,34 @@ func (h *RouteController)DeleteDockerLogs(w http.ResponseWriter, req *http.Reque Host string Service string } - decoder := json.NewDecoder(req.Body) - decoder.Decode(&logItem) + if !decodeBody(w, req, &logItem) { + return + } - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"error": util.DeleteDockerLogs(logItem.Host, logItem.Service)}) + writeJSON(w, http.StatusOK, map[string]interface{}{"error": util.DeleteDockerLogs(logItem.Host, logItem.Service)}) } -func (h *RouteController)AskForDelete(w http.ResponseWriter, req *http.Request) { +func (h *RouteController) AskForDelete(w http.ResponseWriter, req *http.Request) { var logItem struct { Hostname string Token string } - decoder := json.NewDecoder(req.Body) - decoder.Decode(&logItem) + if !decodeBody(w, req, &logItem) { + return + } if !db.IsTokenExists(logItem.Token) { w.WriteHeader(http.StatusUnauthorized) return } - to_delete := []string{} - if len(vars.ToDelete[logItem.Hostname]) != 0 { - to_delete = vars.ToDelete[logItem.Hostname] - vars.ToDelete[logItem.Hostname] = []string{} - } + to_delete := vars.TakeQueuedDeletes(logItem.Hostname) - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"Services": to_delete}) + writeJSON(w, http.StatusOK, map[string]interface{}{"Services": to_delete}) } -func (h *RouteController)DeleteContainer(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyAdminUser(&w, req) { +func (h *RouteController) DeleteContainer(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authAdmin, "") { return } @@ -737,50 +982,44 @@ func (h *RouteController)DeleteContainer(w http.ResponseWriter, req *http.Reques Host string Service string } - decoder := json.NewDecoder(req.Body) - decoder.Decode(&logItem) + if !decodeBody(w, req, &logItem) { + return + } if logItem.Host == "" || logItem.Host == util.GetHost() { dockerContainerID := util.GetDockerContainerID(logItem.Host, logItem.Service) dockerImage, _ := h.DockerService.GetContainerImageNameByContainerID(req.Context(), dockerContainerID) if strings.Contains(dockerImage, "devforth/onlogs") { w.WriteHeader(http.StatusForbidden) - json.NewEncoder(w).Encode(map[string]interface{}{"error": "Can't delete logs of OnLogs container!"}) + writeJSON(w, http.StatusOK, map[string]interface{}{"error": "Can't delete logs of OnLogs container!"}) return } } go containerdb.DeleteContainer(logItem.Host, logItem.Service, true) - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"error": nil}) + ok(w) } -func (h *RouteController)DeleteUser(w http.ResponseWriter, req *http.Request) { - if verifyRequest(&w, req) || !verifyAdminUser(&w, req) { - return - } - - if req.Method != "POST" { - w.WriteHeader(http.StatusNotFound) +func (h *RouteController) DeleteUser(w http.ResponseWriter, req *http.Request) { + if !guard(w, req, authAdmin, "POST") { return } var loginData struct { Login string `json:"login"` } - decoder := json.NewDecoder(req.Body) - decoder.Decode(&loginData) + if !decodeBody(w, req, &loginData) { + return + } if loginData.Login == os.Getenv("ADMIN_USERNAME") { - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]string{"error": "Can't delete admin"}) + fail(w, http.StatusOK, "Can't delete admin") return } - err := userdb.DeleteUser(loginData.Login, loginData.Login) + err := userdb.DeleteUser(loginData.Login) if err != nil { - json.NewEncoder(w).Encode(map[string]string{"error": err.Error()}) + fail(w, http.StatusOK, err.Error()) return } - w.Header().Add("Content-Type", "application/json") - json.NewEncoder(w).Encode(map[string]interface{}{"error": nil}) + ok(w) } diff --git a/application/backend/app/routes/routes_test.go b/application/backend/app/routes/routes_test.go index 5ed960f..be6f23a 100644 --- a/application/backend/app/routes/routes_test.go +++ b/application/backend/app/routes/routes_test.go @@ -21,34 +21,39 @@ import ( "github.com/syndtr/goleveldb/leveldb" ) -func initTestConfig() *RouteController { - cli, _ := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - defer cli.Close() - - dockerService := &docker.DockerService{ - Client: cli, - } +var testCtrl *RouteController - daemonService := &daemon.DaemonService{ - DockerClient: dockerService, +func TestMain(m *testing.M) { + if os.Getenv("JWT_SECRET") == "" { + os.Setenv("JWT_SECRET", "routes-package-test-signing-key") } + // A token is only accepted while its account exists, so the accounts these + // tests sign tokens for have to be present. + os.Setenv("ADMIN_USERNAME", "admin") + userdb.CreateUser("admin", "admin-password-for-tests") + userdb.CreateUser("testuser", "testuser") + userdb.CreateUser("viewer", "viewer-password") + userdb.CreateUser("someuser", "someuser-password") - // Initialize the "Controller" with its dependencies - routerCtrl := &RouteController{ + cli, _ := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + dockerService := &docker.DockerService{Client: cli} + testCtrl = &RouteController{ DockerService: dockerService, - DaemonService: daemonService, + DaemonService: daemon.NewDaemonService(dockerService), } - return routerCtrl + + code := m.Run() + cli.Close() + os.Exit(code) } func TestFrontend(t *testing.T) { - ctrl := initTestConfig() os.Mkdir("dist", 0700) os.WriteFile("dist/index.html", []byte("text"), 0700) req1, _ := http.NewRequest("GET", "/frontend", nil) rr1 := httptest.NewRecorder() - handler1 := http.HandlerFunc(ctrl.Frontend) + handler1 := http.HandlerFunc(testCtrl.Frontend) handler1.ServeHTTP(rr1, req1) body1, _ := io.ReadAll(rr1.Result().Body) if string(body1) != "text" { @@ -57,7 +62,7 @@ func TestFrontend(t *testing.T) { req2, _ := http.NewRequest("GET", "/fasf", nil) rr2 := httptest.NewRecorder() - handler2 := http.HandlerFunc(ctrl.Frontend) + handler2 := http.HandlerFunc(testCtrl.Frontend) handler2.ServeHTTP(rr2, req2) body2, _ := io.ReadAll(rr2.Result().Body) if string(body2) != "text" { @@ -66,27 +71,11 @@ func TestFrontend(t *testing.T) { } func TestCheckCookie(t *testing.T) { - ctrl := initTestConfig() - - req1, _ := http.NewRequest("GET", "/frontend", nil) - rr1 := httptest.NewRecorder() - handler1 := http.HandlerFunc(ctrl.CheckCookie) - handler1.ServeHTTP(rr1, req1) - if rr1.Result().StatusCode != 401 { - t.Error("Should be unauthorized!") + if status, _ := call(t, testCtrl.CheckCookie, authedRequest(t, "", "GET", "/", nil)); status != 401 { + t.Errorf("a request with no cookie returned %d, want 401", status) } - - req2, _ := http.NewRequest("GET", "/", nil) - req2.AddCookie(&http.Cookie{ - Name: "onlogs-cookie", - Value: util.CreateJWT("testuser"), - }) - userdb.CreateUser("testuser", "testuser") - rr2 := httptest.NewRecorder() - handler2 := http.HandlerFunc(ctrl.CheckCookie) - handler2.ServeHTTP(rr2, req2) - if rr2.Result().StatusCode != 200 { - t.Error("Should be unauthorized!") + if status, _ := call(t, testCtrl.CheckCookie, authedRequest(t, "testuser", "GET", "/", nil)); status != 200 { + t.Errorf("a signed request returned %d, want 200", status) } } @@ -95,7 +84,6 @@ func TestGetHosts(t *testing.T) { if err != nil { os.Setenv("DOCKER_HOST", "unix:///var/run/docker.sock") } - ctrl := initTestConfig() os.RemoveAll("leveldb/hosts") os.MkdirAll("leveldb/hosts/Test1/containers/containerTest1", 0700) @@ -111,10 +99,8 @@ func TestGetHosts(t *testing.T) { Value: util.CreateJWT("testuser"), }) - userdb.CreateUser("testuser", "testuser") - rr1 := httptest.NewRecorder() - handler1 := http.HandlerFunc(ctrl.GetHosts) + handler1 := http.HandlerFunc(testCtrl.GetHosts) handler1.ServeHTTP(rr1, req1) b, _ := io.ReadAll(rr1.Result().Body) @@ -171,87 +157,54 @@ func TestGetHosts(t *testing.T) { } } -func TestSizeByAll(t *testing.T) { - ctrl := initTestConfig() - req1, _ := http.NewRequest("GET", "/", nil) - req1.AddCookie(&http.Cookie{ - Name: "onlogs-cookie", - Value: util.CreateJWT("testuser"), - }) - userdb.CreateUser("testuser", "testuser") - rr1 := httptest.NewRecorder() - handler1 := http.HandlerFunc(ctrl.GetSizeByAll) - handler1.ServeHTTP(rr1, req1) - b, _ := io.ReadAll(rr1.Result().Body) - if !strings.Contains(string(b), "\"0.0\"") { - t.Error("Wrong size: ", string(b)) +func TestSizeEndpointsReportAnEmptyStore(t *testing.T) { + cases := []struct { + name string + handler http.HandlerFunc + target string + }{ + {"sizeByAll", testCtrl.GetSizeByAll, "/api/v1/getSizeByAll"}, + {"sizeByService", testCtrl.GetSizeByService, "/api/v1/getSizeByService?service=containerTest1&host=Test1"}, } -} -func TestSizeByService(t *testing.T) { - ctrl := initTestConfig() - req1, _ := http.NewRequest("GET", "/getSizeByService?service=containerTest1&host=Test1", nil) - req1.AddCookie(&http.Cookie{ - Name: "onlogs-cookie", - Value: util.CreateJWT("testuser"), - }) - userdb.CreateUser("testuser", "testuser") - rr1 := httptest.NewRecorder() - handler1 := http.HandlerFunc(ctrl.GetSizeByAll) - handler1.ServeHTTP(rr1, req1) - b, _ := io.ReadAll(rr1.Result().Body) - if !strings.Contains(string(b), "\"0.0\"") { - t.Error("Wrong size: ", string(b)) + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + _, body := call(t, c.handler, authedRequest(t, "testuser", "GET", c.target, nil)) + if !strings.Contains(string(body), "\"0.0\"") { + t.Errorf("%s reported %s, want 0.0", c.name, body) + } + }) } } func TestLogin(t *testing.T) { - ctrl := initTestConfig() - postBody, _ := json.Marshal(map[string]string{ - "Login": "testuser", - "Password": "testsuser", - }) - req1, _ := http.NewRequest("POST", "/", bytes.NewBuffer(postBody)) - userdb.CreateUser("testuser", "testuser") - - rr1 := httptest.NewRecorder() - handler1 := http.HandlerFunc(ctrl.Login) - handler1.ServeHTTP(rr1, req1) - b, _ := io.ReadAll(rr1.Result().Body) - if !strings.Contains(string(b), "Wrong") { - t.Error("Password must be wrong!") + _, wrong := call(t, testCtrl.Login, + authedRequest(t, "", "POST", "/", map[string]string{"Login": "testuser", "Password": "testsuser"})) + if !strings.Contains(string(wrong), "Wrong") { + t.Errorf("a bad password was accepted: %s", wrong) } - postBody2, _ := json.Marshal(map[string]string{ - "Login": "testuser", - "Password": "testuser", - }) - req2, _ := http.NewRequest("POST", "/", bytes.NewBuffer(postBody2)) - rr2 := httptest.NewRecorder() - handler2 := http.HandlerFunc(ctrl.Login) - handler2.ServeHTTP(rr2, req2) - b2, _ := io.ReadAll(rr2.Result().Body) - if !strings.Contains(string(b2), "null") { - t.Error("Password must be wrong!") + _, right := call(t, testCtrl.Login, + authedRequest(t, "", "POST", "/", map[string]string{"Login": "testuser", "Password": "testuser"})) + if !strings.Contains(string(right), "null") { + t.Errorf("the correct password was rejected: %s", right) } } func TestLogout(t *testing.T) { - ctrl := initTestConfig() postBody, _ := json.Marshal(map[string]string{ "Login": "testuser", "Password": "testuser", }) req1, _ := http.NewRequest("POST", "/", bytes.NewBuffer(postBody)) - userdb.CreateUser("testuser", "testuser") rr1 := httptest.NewRecorder() - handler1 := http.HandlerFunc(ctrl.Login) + handler1 := http.HandlerFunc(testCtrl.Login) handler1.ServeHTTP(rr1, req1) rr2 := httptest.NewRecorder() req1.AddCookie(rr1.Result().Cookies()[0]) - handler2 := http.HandlerFunc(ctrl.Logout) + handler2 := http.HandlerFunc(testCtrl.Logout) handler2.ServeHTTP(rr2, req1) if rr2.Result().Cookies()[0].Value != "toDelete" { @@ -260,15 +213,13 @@ func TestLogout(t *testing.T) { } func TestGetStats(t *testing.T) { - ctrl := initTestConfig() postBody1, _ := json.Marshal(map[string]string{ "Login": "testuser", "Password": "testuser", }) req1, _ := http.NewRequest("POST", "/", bytes.NewBuffer(postBody1)) - userdb.CreateUser("testuser", "testuser") rr1 := httptest.NewRecorder() - handler1 := http.HandlerFunc(ctrl.Login) + handler1 := http.HandlerFunc(testCtrl.Login) handler1.ServeHTTP(rr1, req1) rr2 := httptest.NewRecorder() @@ -287,7 +238,7 @@ func TestGetStats(t *testing.T) { }) req2, _ := http.NewRequest("POST", "/", bytes.NewBuffer(postBody2)) req2.AddCookie(rr1.Result().Cookies()[0]) - handler2 := http.HandlerFunc(ctrl.GetStats) + handler2 := http.HandlerFunc(testCtrl.GetStats) handler2.ServeHTTP(rr2, req2) b, _ := io.ReadAll(rr2.Result().Body) @@ -301,19 +252,16 @@ func TestGetStats(t *testing.T) { } func TestGetChartData(t *testing.T) { - ctrl := initTestConfig() postBody1, _ := json.Marshal(map[string]string{ "Login": "testuser", "Password": "testuser", }) req1, _ := http.NewRequest("POST", "/", bytes.NewBuffer(postBody1)) - userdb.CreateUser("testuser", "testuser") rr1 := httptest.NewRecorder() - handler1 := http.HandlerFunc(ctrl.Login) + handler1 := http.HandlerFunc(testCtrl.Login) handler1.ServeHTTP(rr1, req1) cur_db, _ := leveldb.OpenFile("leveldb/hosts/test/statistics", nil) - vars.Stat_Hosts_DBs["test"] = cur_db vars.Container_Stat_Counter["test/test"] = map[string]uint64{"error": 2, "debug": 1, "info": 3, "warn": 5, "meta": 0, "other": 4} vars.Stat_Containers_DBs["test/test"] = cur_db to_put, _ := json.Marshal(vars.Container_Stat_Counter["test/test"]) @@ -329,7 +277,7 @@ func TestGetChartData(t *testing.T) { }) req2, _ := http.NewRequest("POST", "/", bytes.NewBuffer(postBody2)) req2.AddCookie(rr1.Result().Cookies()[0]) - handler2 := http.HandlerFunc(ctrl.GetChartData) + handler2 := http.HandlerFunc(testCtrl.GetChartData) handler2.ServeHTTP(rr2, req2) res := map[string]map[string]int{} diff --git a/application/backend/app/routes/security_test.go b/application/backend/app/routes/security_test.go new file mode 100644 index 0000000..fd64a0d --- /dev/null +++ b/application/backend/app/routes/security_test.go @@ -0,0 +1,347 @@ +package routes + +import ( + "bytes" + "crypto/tls" + "encoding/json" + "io" + "net/http" + "net/http/httptest" + "os" + "runtime" + "strconv" + "strings" + "testing" + "time" + + "github.com/devforth/OnLogs/app/db" + "github.com/devforth/OnLogs/app/statistics" + "github.com/devforth/OnLogs/app/userdb" + "github.com/devforth/OnLogs/app/util" + "github.com/devforth/OnLogs/app/vars" +) + +func TestFrontendDoesNotServeFilesOutsideDist(t *testing.T) { + os.MkdirAll("dist", 0o700) + os.WriteFile("dist/index.html", []byte("text"), 0o600) + + os.MkdirAll("leveldb_probe", 0o700) + os.WriteFile("leveldb_probe/JWT_secret", []byte("REAL-ONLOGS-JWT-SECRET"), 0o600) + t.Cleanup(func() { os.RemoveAll("leveldb_probe") }) + + for _, target := range []string{ + "/?x=/../../leveldb_probe/JWT_secret", + "/index.html?x=/../../leveldb_probe/JWT_secret", + "/?/../../leveldb_probe/JWT_secret", + } { + req, _ := http.NewRequest("GET", target, nil) + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.Frontend).ServeHTTP(rr, req) + body, _ := io.ReadAll(rr.Result().Body) + if strings.Contains(string(body), "REAL-ONLOGS-JWT-SECRET") { + t.Fatalf("arbitrary file read through %q: %s", target, string(body)) + } + } +} + +func TestFrontendStripsPathPrefixOnlyAtTheFront(t *testing.T) { + t.Setenv("ONLOGS_PATH_PREFIX", "/logs") + + os.MkdirAll("dist/assets", 0o700) + os.WriteFile("dist/index.html", []byte("text"), 0o600) + os.WriteFile("dist/assets/logs-panel.js", []byte("PANEL_ASSET"), 0o600) + t.Cleanup(func() { os.RemoveAll("dist/assets") }) + + req, _ := http.NewRequest("GET", "/logs/assets/logs-panel.js", nil) + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.Frontend).ServeHTTP(rr, req) + body, _ := io.ReadAll(rr.Result().Body) + if string(body) != "PANEL_ASSET" { + t.Fatalf("expected the asset, got %q", string(body)) + } +} + +func adminOnlyRequest(t *testing.T, handler http.HandlerFunc, method, target string) int { + t.Helper() + os.Setenv("ADMIN_USERNAME", "admin") + + req, _ := http.NewRequest(method, target, nil) + req.AddCookie(&http.Cookie{Name: "onlogs-cookie", Value: util.CreateJWT("viewer")}) + rr := httptest.NewRecorder() + handler.ServeHTTP(rr, req) + return rr.Result().StatusCode +} + +func TestGetSecretIsAdminOnly(t *testing.T) { + if code := adminOnlyRequest(t, testCtrl.GetSecret, "GET", "/api/v1/getSecret"); code != http.StatusForbidden { + t.Fatalf("a non-admin account minted an agent token: status %d", code) + } +} + +func TestGetUsersIsAdminOnly(t *testing.T) { + if code := adminOnlyRequest(t, testCtrl.GetUsers, "GET", "/api/v1/getUsers"); code != http.StatusForbidden { + t.Fatalf("a non-admin account enumerated every username: status %d", code) + } +} + +func TestAddHostRejectsNamesThatLeaveTheTree(t *testing.T) { + token := db.CreateOnLogsToken() + + for _, payload := range []map[string]interface{}{ + {"Hostname": "../../../../PWNED_HOST", "Token": token, "Services": []string{"c"}}, + {"Hostname": "realhost", "Token": token, "Services": []string{"../../../../PWNED_SERVICE"}}, + } { + body, _ := json.Marshal(payload) + req, _ := http.NewRequest("POST", "/api/v1/addHost", bytes.NewBuffer(body)) + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.AddHost).ServeHTTP(rr, req) + + if code := rr.Result().StatusCode; code != http.StatusBadRequest { + t.Errorf("addHost accepted %v: status %d", payload["Hostname"], code) + } + } + + // Assert on exactly the paths MkdirAll would build, not on names relative to + // the package directory β€” those resolve elsewhere and silently pass. + for _, leaked := range []string{ + "leveldb/hosts/../../../../PWNED_HOST", + "leveldb/hosts/realhost/containers/../../../../PWNED_SERVICE", + } { + if _, err := os.Stat(leaked); err == nil { + os.RemoveAll(leaked) + t.Errorf("addHost created %s outside leveldb/hosts", leaked) + } + } + entries, _ := os.ReadDir("leveldb/hosts") + for _, entry := range entries { + if !util.IsSafeName(entry.Name()) { + t.Errorf("addHost created an unsafe host directory: %q", entry.Name()) + } + } +} + +func TestAddLogLineRejectsNamesThatLeaveTheTree(t *testing.T) { + token := db.CreateOnLogsToken() + + body, _ := json.Marshal(map[string]interface{}{ + "Token": token, + "Host": "../../../../PWNED_INGEST", + "Container": "c", + "LogLine": []string{"2026-02-10T12:56:09.230421754Z", "hello"}, + }) + req, _ := http.NewRequest("POST", "/api/v1/addLogLine", bytes.NewBuffer(body)) + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.AddLogLine).ServeHTTP(rr, req) + + if code := rr.Result().StatusCode; code != http.StatusBadRequest { + t.Errorf("addLogLine accepted a traversing host: status %d", code) + } + for _, leaked := range []string{"../../../../PWNED_INGEST", "leveldb/hosts/../../../../PWNED_INGEST"} { + if _, err := os.Stat(leaked); err == nil { + os.RemoveAll(leaked) + t.Errorf("addLogLine created %s outside leveldb/hosts", leaked) + } + } +} + +func oversizedJSONBody() []byte { + body := []byte(`{"pad":"`) + body = append(body, bytes.Repeat([]byte("A"), 4<<20)...) + return append(body, []byte(`"}`)...) +} + +func TestHandlersRejectOversizedRequestBodies(t *testing.T) { + os.Setenv("ADMIN_USERNAME", "admin") + + cases := []struct { + name string + handler http.HandlerFunc + }{ + {"updateUserSettings", testCtrl.UpdateUserSettings}, + {"login", testCtrl.Login}, + {"changeFavorite", testCtrl.ChangeFavourite}, + {"addLogLine", testCtrl.AddLogLine}, + } + + for _, c := range cases { + req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(oversizedJSONBody())) + req.AddCookie(&http.Cookie{Name: "onlogs-cookie", Value: util.CreateJWT("admin")}) + rr := httptest.NewRecorder() + c.handler.ServeHTTP(rr, req) + + if code := rr.Result().StatusCode; code == http.StatusOK { + t.Errorf("%s accepted a 4 MiB request body: status %d", c.name, code) + } + } +} + +func TestLoginCookieIsHttpOnlyAndUsesARelativeMaxAge(t *testing.T) { + userdb.CreateUser("cookieuser", "cookiepass") + + body, _ := json.Marshal(map[string]string{"Login": "cookieuser", "Password": "cookiepass"}) + req, _ := http.NewRequest("POST", "/api/v1/login", bytes.NewBuffer(body)) + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.Login).ServeHTTP(rr, req) + + cookies := rr.Result().Cookies() + if len(cookies) == 0 { + t.Fatalf("login set no cookie: %s", rr.Body.String()) + } + c := cookies[0] + + if !c.HttpOnly { + t.Error("session cookie is readable from JavaScript, so any XSS lifts the session") + } + if c.MaxAge > 7*24*3600 { + t.Errorf("Max-Age is %d seconds (~%d years); it should be a relative lifetime, not an absolute epoch", + c.MaxAge, c.MaxAge/(365*24*3600)) + } + if c.MaxAge <= 0 { + t.Errorf("Max-Age is %d, the session would not persist", c.MaxAge) + } +} + +func TestLoginCookieIsSecureOverTLS(t *testing.T) { + userdb.CreateUser("cookieuser", "cookiepass") + + body, _ := json.Marshal(map[string]string{"Login": "cookieuser", "Password": "cookiepass"}) + req, _ := http.NewRequest("POST", "https://onlogs.example/api/v1/login", bytes.NewBuffer(body)) + req.TLS = &tls.ConnectionState{} + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.Login).ServeHTTP(rr, req) + + cookies := rr.Result().Cookies() + if len(cookies) == 0 { + t.Fatalf("login set no cookie: %s", rr.Body.String()) + } + if !cookies[0].Secure { + t.Error("session cookie issued over TLS is not marked Secure") + } +} + +func TestGetLogsStreamRejectsAForeignOrigin(t *testing.T) { + + req, _ := http.NewRequest("GET", "/api/v1/getLogsStream?host="+util.GetHost()+"&id=somecontainer", nil) + req.Host = "onlogs.example" + req.Header.Set("Origin", "http://evil.example") + req.Header.Set("Connection", "Upgrade") + req.Header.Set("Upgrade", "websocket") + req.Header.Set("Sec-WebSocket-Version", "13") + req.Header.Set("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==") + req.AddCookie(&http.Cookie{Name: "onlogs-cookie", Value: util.CreateJWT("admin")}) + + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.GetLogsStream).ServeHTTP(rr, req) + + if code := rr.Result().StatusCode; code != http.StatusForbidden { + t.Errorf("a cross-origin websocket handshake was not rejected: status %d", code) + } + if got := vars.ConnectionCount(util.GetHost() + "/somecontainer"); got != 0 { + t.Fatalf("a failed upgrade stored %d connection(s); a background goroutine will dereference them", got) + } +} + +func TestLoginRateLimitsRepeatedFailures(t *testing.T) { + userdb.CreateUser("ratelimited", "correct-horse") + + post := func(password string) int { + body, _ := json.Marshal(map[string]string{"Login": "ratelimited", "Password": password}) + req, _ := http.NewRequest("POST", "/api/v1/login", bytes.NewBuffer(body)) + req.RemoteAddr = "203.0.113.9:34567" + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.Login).ServeHTTP(rr, req) + return rr.Result().StatusCode + } + + for i := 0; i < 20; i++ { + post("wrong-" + strconv.Itoa(i)) + } + + if code := post("correct-horse"); code != http.StatusTooManyRequests { + t.Fatalf("20 failed logins from one address did not trigger a backoff: status %d", code) + } +} + +func TestAddLogLineDoesNotSpawnAWorkerPerLogLine(t *testing.T) { + token := db.CreateOnLogsToken() + before := statistics.WorkerCount() + t.Cleanup(func() { statistics.StopWorker("statsprobehost", "statsprobecontainer") }) + + ingest := func(count int) { + for i := 0; i < count; i++ { + body, _ := json.Marshal(map[string]interface{}{ + "Token": token, + "Host": "statsprobehost", + "Container": "statsprobecontainer", + "LogLine": []string{"2026-02-10T12:56:09.230421754Z", "line " + strconv.Itoa(i)}, + }) + req, _ := http.NewRequest("POST", "/api/v1/addLogLine", bytes.NewBuffer(body)) + rr := httptest.NewRecorder() + http.HandlerFunc(testCtrl.AddLogLine).ServeHTTP(rr, req) + if code := rr.Result().StatusCode; code != http.StatusOK { + t.Fatalf("ingestion failed: status %d", code) + } + } + time.Sleep(250 * time.Millisecond) + } + + // Warm up: the first line legitimately starts one worker, which opens + // databases and so brings its own goroutines with it. + ingest(25) + settled := runtime.NumGoroutine() + + ingest(25) + growth := runtime.NumGoroutine() - settled + + if got := statistics.WorkerCount() - before; got != 1 { + t.Errorf("expected exactly one registered statistics worker, got %d", got) + } + if growth > 5 { + t.Fatalf("a further 25 log lines started %d more goroutines; the leak scales with ingestion and each worker zeroes the live counter", growth) + } +} + +// The Content-Type was previously set per handler; a helper now owns it, so one +// endpoint of each shape has to prove the header survives. +func TestJSONEndpointsSetTheirContentType(t *testing.T) { + os.Setenv("ADMIN_USERNAME", "admin") + + cases := []struct { + name string + handler http.HandlerFunc + user string + }{ + {"checkCookie", testCtrl.CheckCookie, "testuser"}, + {"getHosts", testCtrl.GetHosts, "testuser"}, + {"getUsers", testCtrl.GetUsers, "admin"}, + {"getSizeByAll", testCtrl.GetSizeByAll, "testuser"}, + {"getGroups", testCtrl.GetGroups, "testuser"}, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + req, _ := http.NewRequest("GET", "/", nil) + req.AddCookie(&http.Cookie{Name: "onlogs-cookie", Value: util.CreateJWT(c.user)}) + rr := httptest.NewRecorder() + c.handler.ServeHTTP(rr, req) + + if got := rr.Header().Get("Content-Type"); !strings.HasPrefix(got, "application/json") { + t.Errorf("%s replied with Content-Type %q, want application/json", c.name, got) + } + }) + } +} + +func TestRejectedRequestsStillSetContentType(t *testing.T) { + + req, _ := http.NewRequest("GET", "/", nil) + rr := httptest.NewRecorder() + testCtrl.CheckCookie(rr, req) + + if rr.Code != http.StatusUnauthorized { + t.Fatalf("expected 401, got %d", rr.Code) + } + if got := rr.Header().Get("Content-Type"); !strings.HasPrefix(got, "application/json") { + t.Errorf("a 401 replied with Content-Type %q, want application/json", got) + } +} diff --git a/application/backend/app/statistics/keys_test.go b/application/backend/app/statistics/keys_test.go new file mode 100644 index 0000000..197ed4d --- /dev/null +++ b/application/backend/app/statistics/keys_test.go @@ -0,0 +1,94 @@ +package statistics + +import ( + "os" + "testing" + "time" + + "github.com/devforth/OnLogs/app/containerdb" + "github.com/devforth/OnLogs/app/util" + "github.com/devforth/OnLogs/app/vars" +) + +func TestSavedStatisticsKeysParseAsTimestamps(t *testing.T) { + host, container := "StatKeyHost", "StatKeyContainer" + _ = os.RemoveAll("leveldb/hosts/" + host) + t.Cleanup(func() { _ = os.RemoveAll("leveldb/hosts/" + host) }) + + vars.Mutex.Lock() + delete(vars.Container_Stat_Counter, host+"/"+container) + vars.Mutex.Unlock() + + logsDB := util.GetDB(host, container, "logs") + if logsDB == nil { + t.Fatal("could not open the logs database") + } + writeLines := func(base time.Time, count int) { + for i := 0; i < count; i++ { + ts := base.Add(time.Duration(i) * time.Second).UTC().Format(time.RFC3339Nano) + if err := containerdb.PutLogMessage(logsDB, host, container, []string{ts, "ERROR something"}); err != nil { + t.Fatal(err) + } + } + } + + // First round takes the "no statistics yet" branch and saves under "now". + writeLines(time.Now().Add(-time.Hour), 3) + restartStats(host, container) + + // Lines arriving after that point drive the incremental branch, where the + // cursor the forward scan returns becomes the key it saves under. + writeLines(time.Now().Add(time.Minute), 3) + restartStats(host, container) + + statsDB := util.GetDB(host, container, "statistics") + if statsDB == nil { + t.Fatal("no statistics database") + } + iter := statsDB.NewIterator(nil, nil) + defer iter.Release() + + written := 0 + for iter.Next() { + key := string(iter.Key()) + written++ + if _, err := time.Parse(time.RFC3339Nano, key); err != nil { + t.Fatalf("statistics key %q is not a timestamp, so every chart point fails to parse: %v", key, err) + } + } + if written == 0 { + t.Fatal("no statistics were written at all") + } +} + +// The scan cursor is deliberately a full log key, so that paging can identify one +// row among several in the same instant. +func TestSaveStatsAlwaysWritesAParseableKey(t *testing.T) { + host, container := "StatCursorHost", "StatCursorContainer" + _ = os.RemoveAll("leveldb/hosts/" + host) + t.Cleanup(func() { _ = os.RemoveAll("leveldb/hosts/" + host) }) + + db := util.GetDB(host, container, "statistics") + if db == nil { + t.Fatal("could not open the statistics database") + } + + fullLogKey := "2026-02-10T12:44:02.123456789Z +1786097928311912188-9" + saveStats(db, containerdb.NewStatCounter(), fullLogKey) + saveStats(db, containerdb.NewStatCounter(), "not a timestamp at all") + + iter := db.NewIterator(nil, nil) + defer iter.Release() + + written := 0 + for iter.Next() { + written++ + key := string(iter.Key()) + if _, err := time.Parse(time.RFC3339Nano, key); err != nil { + t.Errorf("saveStats wrote %q, which every reader fails to parse: %v", key, err) + } + } + if written != 2 { + t.Fatalf("expected 2 statistics entries, got %d", written) + } +} diff --git a/application/backend/app/statistics/monotonic_test.go b/application/backend/app/statistics/monotonic_test.go new file mode 100644 index 0000000..8b4c56e --- /dev/null +++ b/application/backend/app/statistics/monotonic_test.go @@ -0,0 +1,52 @@ +package statistics + +import ( + "os" + "testing" + + "github.com/devforth/OnLogs/app/containerdb" + "github.com/devforth/OnLogs/app/util" + "github.com/devforth/OnLogs/app/vars" +) + +// Lives here, not in containerdb, because resetInMemoryStats is unexported. +// Without this the counter resets every minute and rate() is meaningless. +func TestLogLineCounterSurvivesStatsReset(t *testing.T) { + const host, container = "monotonic-host", "monotonic-container" + location := host + "/" + container + defer os.RemoveAll("leveldb/hosts/" + host) + + db := util.GetDB(host, container, "logs") + if db == nil { + t.Fatal("no logs db") + } + put := func(n int) { + for i := 0; i < n; i++ { + if err := containerdb.PutLogMessage(db, host, container, []string{ + "2026-08-08T10:00:00.000000000Z", "ERROR something failed", + }); err != nil { + t.Fatalf("PutLogMessage: %v", err) + } + } + } + + before := containerdb.LogLineCounts()[location]["error"] + put(10) + if got := containerdb.LogLineCounts()[location]["error"]; got != before+10 { + t.Fatalf("after 10 lines: got %d, want %d", got, before+10) + } + + resetInMemoryStats(location) + + vars.Mutex.Lock() + live := vars.Container_Stat_Counter[location]["error"] + vars.Mutex.Unlock() + if live != 0 { + t.Fatalf("resetInMemoryStats left the live counter at %d, want 0", live) + } + + put(10) + if got := containerdb.LogLineCounts()[location]["error"]; got != before+20 { + t.Errorf("across a stats reset: got %d, want %d", got, before+20) + } +} diff --git a/application/backend/app/statistics/overcount_test.go b/application/backend/app/statistics/overcount_test.go new file mode 100644 index 0000000..44d1252 --- /dev/null +++ b/application/backend/app/statistics/overcount_test.go @@ -0,0 +1,176 @@ +package statistics + +import ( + "encoding/json" + "os" + "testing" + "time" + + "github.com/devforth/OnLogs/app/containerdb" + "github.com/devforth/OnLogs/app/util" + "github.com/devforth/OnLogs/app/vars" +) + +// RFC3339Nano trims trailing zeros, which breaks both the 30-character minimum +// PutLogMessage enforces and lexicographic ordering in leveldb. +const fixedWidthNanos = "2006-01-02T15:04:05.000000000Z" + +func persistedMeta(t *testing.T, host string, container string) uint64 { + t.Helper() + + db := util.GetDB(host, container, "statistics") + if db == nil { + t.Fatal("no statistics database") + } + iter := db.NewIterator(nil, nil) + defer iter.Release() + + var total uint64 + for iter.Next() { + stats := map[string]uint64{} + if err := json.Unmarshal(iter.Value(), &stats); err != nil { + t.Fatalf("unparseable statistics record %q: %v", iter.Key(), err) + } + t.Logf(" %s meta:%d", iter.Key(), stats["meta"]) + total += stats["meta"] + } + return total +} + +// Drives restartStats the way the once-a-minute worker does. Each entry in +// arrivals is how many log lines landed during one flush interval. +func runFlushes(t *testing.T, name string, arrivals []int) (uint64, uint64) { + t.Helper() + + host, container := "OverCount"+name, "svc" + os.RemoveAll("leveldb/hosts/" + host) + t.Cleanup(func() { + for _, dbType := range []string{"logs", "statuses", "statistics"} { + util.ResetDB(host, container, dbType) + } + os.RemoveAll("leveldb/hosts/" + host) + vars.Mutex.Lock() + delete(vars.Container_Stat_Counter, host+"/"+container) + vars.Mutex.Unlock() + }) + os.MkdirAll("leveldb/hosts/"+host+"/containers/"+container, 0700) + + logsDB := util.GetDB(host, container, "logs") + if logsDB == nil { + t.Fatal("no logs database") + } + + // The first flush stamps the cursor at now, so every line has to sort after it. + restartStats(host, container) + + at := time.Now().UTC().Add(time.Hour) + var written uint64 + for _, count := range arrivals { + for i := 0; i < count; i++ { + at = at.Add(time.Second) + line := []string{at.Format(fixedWidthNanos), "ONLOGS: Container listening stopped! (unexpected EOF)"} + if err := containerdb.PutLogMessage(logsDB, host, container, line); err != nil { + t.Fatalf("put: %v", err) + } + written++ + } + restartStats(host, container) + } + + t.Logf("%s: %d log lines ->", name, written) + return written, persistedMeta(t, host, container) +} + +func TestStatsDoNotOverCountAcrossFlushes(t *testing.T) { + arrivals := []int{} + for i := 0; i < 14; i++ { + arrivals = append(arrivals, 1, 0) + } + arrivals = append(arrivals, 1, 1, 0, 1, 1, 0) + + lines, persisted := runFlushes(t, "Drop", arrivals) + if lines != 18 { + t.Fatalf("meant to write 18 lines, wrote %d", lines) + } + if persisted != lines { + t.Errorf("%d log lines are persisted as meta=%d", lines, persisted) + } +} + +func TestStatsDoNotUnderCountAfterIdleFlush(t *testing.T) { + lines, persisted := runFlushes(t, "Burst", []int{1, 0, 3, 0, 0}) + if persisted != lines { + t.Errorf("%d log lines are persisted as meta=%d", lines, persisted) + } +} + +func TestStatsCountLinesOlderThanTheFirstFlush(t *testing.T) { + host, container := "LateIngest", "svc" + os.RemoveAll("leveldb/hosts/" + host) + t.Cleanup(func() { + for _, dbType := range []string{"logs", "statuses", "statistics"} { + util.ResetDB(host, container, dbType) + } + os.RemoveAll("leveldb/hosts/" + host) + vars.Mutex.Lock() + delete(vars.Container_Stat_Counter, host+"/"+container) + vars.Mutex.Unlock() + }) + os.MkdirAll("leveldb/hosts/"+host+"/containers/"+container, 0700) + + logsDB := util.GetDB(host, container, "logs") + if logsDB == nil { + t.Fatal("no logs database") + } + + restartStats(host, container) + + at := time.Now().UTC().Add(-time.Hour) + for i := 0; i < 3; i++ { + at = at.Add(time.Second) + line := []string{at.Format(fixedWidthNanos), "ONLOGS: Container listening started!"} + if err := containerdb.PutLogMessage(logsDB, host, container, line); err != nil { + t.Fatalf("put: %v", err) + } + } + restartStats(host, container) + + if persisted := persistedMeta(t, host, container); persisted != 3 { + t.Errorf("3 log lines predating the first flush are persisted as meta=%d", persisted) + } +} + +func TestChartBucketsSumEveryRecordInThem(t *testing.T) { + host, container := "ChartBucket", "svc" + os.RemoveAll("leveldb/hosts/" + host) + t.Cleanup(func() { + util.ResetDB(host, container, "statistics") + os.RemoveAll("leveldb/hosts/" + host) + }) + os.MkdirAll("leveldb/hosts/"+host+"/containers/"+container, 0700) + + db := util.GetDB(host, container, "statistics") + if db == nil { + t.Fatal("no statistics database") + } + now := time.Now().UTC() + for i, errors := range []uint64{7, 5} { + record, _ := json.Marshal(map[string]uint64{"error": errors}) + key := now.Add(time.Duration(-i) * time.Second).Format(time.RFC3339Nano) + if err := db.Put([]byte(key), record, nil); err != nil { + t.Fatalf("seeding: %v", err) + } + } + + chart := GetChartData(host, container, "hour", 2) + delete(chart, "now") + + var total uint64 + for bucket, stats := range chart { + t.Logf(" %s error:%d", bucket, stats["error"]) + total += stats["error"] + } + if total != 12 { + t.Errorf("the two records hold 12 errors, the chart reports %d", total) + } +} diff --git a/application/backend/app/statistics/race_test.go b/application/backend/app/statistics/race_test.go new file mode 100644 index 0000000..5617bba --- /dev/null +++ b/application/backend/app/statistics/race_test.go @@ -0,0 +1,75 @@ +package statistics + +import ( + "os" + "testing" + + "github.com/devforth/OnLogs/app/containerdb" + "github.com/devforth/OnLogs/app/vars" +) + +// Mirrors containerdb.countLogStatus: the writer that runs on every log line. +func countConcurrently(location string, stop <-chan struct{}, done chan<- struct{}) { + for { + select { + case <-stop: + close(done) + return + default: + } + vars.Mutex.Lock() + if vars.Container_Stat_Counter[location] == nil { + vars.Container_Stat_Counter[location] = map[string]uint64{} + } + vars.Container_Stat_Counter[location]["error"]++ + vars.Mutex.Unlock() + } +} + +func TestGetStatisticsByServiceDoesNotHandOutTheLiveCounter(t *testing.T) { + host, service := "StatRaceHost", "StatRaceCont" + location := host + "/" + service + _ = os.RemoveAll("leveldb/hosts/" + host) + + seedCounter(location, containerdb.NewStatCounter()) + + stop := make(chan struct{}) + done := make(chan struct{}) + go countConcurrently(location, stop, done) + + // value < 1 is the path /getStats takes for the live counters, and the + // returned map is then marshalled by the handler with no lock held. + for i := 0; i < 300; i++ { + result := GetStatisticsByService(host, service, 0) + for _, key := range []string{"error", "debug", "info", "warn", "meta", "other"} { + _ = result[key] + } + } + + close(stop) + <-done +} + +func TestGetChartDataDoesNotHandOutTheLiveCounter(t *testing.T) { + host, service := "ChartRaceHost", "ChartRaceCont" + location := host + "/" + service + _ = os.RemoveAll("leveldb/hosts/" + host) + + seedCounter(location, containerdb.NewStatCounter()) + + stop := make(chan struct{}) + done := make(chan struct{}) + go countConcurrently(location, stop, done) + + for i := 0; i < 200; i++ { + result := GetChartData(host, service, "hour", 2) + if now := result["now"]; now != nil { + for _, key := range []string{"error", "debug", "info", "warn", "meta", "other"} { + _ = now[key] + } + } + } + + close(stop) + <-done +} diff --git a/application/backend/app/statistics/registry.go b/application/backend/app/statistics/registry.go new file mode 100644 index 0000000..a9d5b70 --- /dev/null +++ b/application/backend/app/statistics/registry.go @@ -0,0 +1,86 @@ +package statistics + +import ( + "context" + "sync" +) + +// One statistics worker per host/container, shared by the docker streamer and +// the agent ingestion route. +type workerHandle struct { + cancel context.CancelFunc + id uint64 +} + +var ( + workersMutex sync.Mutex + workerSeq uint64 + workers = map[string]*workerHandle{} +) + +func WorkerKey(host string, container string) string { + return host + "/" + container +} + +func registerWorker(location string, cancel context.CancelFunc) (uint64, bool) { + workersMutex.Lock() + defer workersMutex.Unlock() + + if _, exists := workers[location]; exists { + return 0, false + } + workerSeq++ + workers[location] = &workerHandle{cancel: cancel, id: workerSeq} + return workerSeq, true +} + +// A worker can take seconds to unwind after its context is cancelled, by which +// time a replacement may already be registered. Only retire our own. +func retireWorker(location string, id uint64) { + workersMutex.Lock() + defer workersMutex.Unlock() + + if handle, exists := workers[location]; exists && handle.id == id { + delete(workers, location) + } +} + +// EnsureWorker starts a worker for host/container unless one already runs. +func EnsureWorker(ctx context.Context, host string, container string) bool { + location := WorkerKey(host, container) + workerCtx, cancel := context.WithCancel(ctx) + + id, registered := registerWorker(location, cancel) + if !registered { + cancel() + return false + } + + go func() { + defer cancel() + defer retireWorker(location, id) + RunStatisticForContainerWithContext(workerCtx, host, container) + }() + return true +} + +func StopWorker(host string, container string) { + location := WorkerKey(host, container) + + workersMutex.Lock() + handle, exists := workers[location] + if exists { + delete(workers, location) + } + workersMutex.Unlock() + + if exists { + handle.cancel() + } +} + +func WorkerCount() int { + workersMutex.Lock() + defer workersMutex.Unlock() + return len(workers) +} diff --git a/application/backend/app/statistics/registry_test.go b/application/backend/app/statistics/registry_test.go new file mode 100644 index 0000000..d777eb6 --- /dev/null +++ b/application/backend/app/statistics/registry_test.go @@ -0,0 +1,85 @@ +package statistics + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/devforth/OnLogs/app/vars" +) + +// Workers zero the live counter on their own schedule, so seeding it from a +// test has to take the same lock they do. +func seedCounter(location string, stats map[string]uint64) { + vars.Mutex.Lock() + defer vars.Mutex.Unlock() + vars.Container_Stat_Counter[location] = stats +} + +// One worker per host/container, shared by the docker streamer and the agent +// ingestion route. +func TestEnsureWorkerRejectsDuplicates(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + baseline := WorkerCount() + t.Cleanup(func() { StopWorker("host", "container") }) + + first := EnsureWorker(ctx, "host", "container") + second := EnsureWorker(ctx, "host", "container") + + if !first { + t.Fatal("first registration must succeed") + } + if second { + t.Fatal("duplicate registration must be rejected") + } + if got := WorkerCount(); got != baseline+1 { + t.Fatalf("expected exactly one new worker, got %d (baseline %d)", got, baseline) + } +} + +func TestWorkerChurnDoesNotLeak(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + baseline := WorkerCount() + host := "churn-host" + for i := 0; i < 300; i++ { + container := fmt.Sprintf("ephemeral-%d", i) + EnsureWorker(ctx, host, container) + StopWorker(host, container) + } + + if got := WorkerCount(); got != baseline { + t.Fatalf("expected %d workers after churn, got %d", baseline, got) + } +} + +func TestWorkerCreatesItsCounterAndDatabase(t *testing.T) { + const location = "Test/TestContainer" + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + go RunStatisticForContainerWithContext(ctx, "Test", "TestContainer") + + // Polled, not slept: under -race the worker takes far longer to reach its + // first flush than any fixed delay worth hard-coding. + deadline := time.Now().Add(15 * time.Second) + for time.Now().Before(deadline) { + vars.DBMutex.RLock() + statsDB := vars.Stat_Containers_DBs[location] + vars.DBMutex.RUnlock() + + vars.Mutex.Lock() + _, counted := vars.Container_Stat_Counter[location] + vars.Mutex.Unlock() + + if statsDB != nil && counted { + return + } + time.Sleep(20 * time.Millisecond) + } + t.Fatal("the worker never created its counter and statistics database") +} diff --git a/application/backend/app/statistics/statistics.go b/application/backend/app/statistics/statistics.go index 3a20cc6..99a7649 100644 --- a/application/backend/app/statistics/statistics.go +++ b/application/backend/app/statistics/statistics.go @@ -12,26 +12,44 @@ import ( "github.com/syndtr/goleveldb/leveldb" ) +// The caller must never receive the live map: it is written on every log line. +func snapshotCounter(location string) map[string]uint64 { + vars.Mutex.Lock() + defer vars.Mutex.Unlock() + + snapshot := containerdb.NewStatCounter() + for key, value := range vars.Container_Stat_Counter[location] { + snapshot[key] = value + } + return snapshot +} + func restartStats(host string, container string) { current_db := util.GetDB(host, container, "statistics") + if current_db == nil { + return + } location := host if container != "" { location += "/" + container } - current_datetime := time.Now().UTC().Format("2006-01-02T15:04:05.999999999Z") - last_stat_time := getLastStatTime(current_db) if last_stat_time == "" { - last_stat_time = current_datetime - calc_stat := collectLogsBackward(host, container, last_stat_time) - saveStats(current_db, calc_stat, last_stat_time) + // Anchored to the newest line actually seen, never to the clock: the + // clock is ahead of lines docker has not replayed yet, and the forward + // scan would then seek straight past them. + calc_stat, newest := collectLogs(host, container, "", false) + if newest != "" { + saveStats(current_db, calc_stat, newest) + } } else { - calc_stat, new_datetime := collectLogsForward(host, container, last_stat_time) - if last_stat_time == new_datetime { - new_datetime = current_datetime + calc_stat, new_datetime := collectLogs(host, container, last_stat_time, true) + // Nothing new: saving would rewrite the previous interval's record with + // an empty one and move the cursor off the log timeline onto the clock. + if last_stat_time != new_datetime { + saveStats(current_db, calc_stat, new_datetime) } - saveStats(current_db, calc_stat, new_datetime) } resetInMemoryStats(location) @@ -48,70 +66,60 @@ func getLastStatTime(db *leveldb.DB) string { return string(iter.Key()) } -func collectLogsBackward(host, container, until string) map[string]uint64 { - calc_stat := map[string]uint64{"error": 0, "debug": 0, "info": 0, "warn": 0, "meta": 0, "other": 0} +// A forward scan returns the cursor it finished on; a backward scan returns the +// newest key it saw, which is where a first cursor belongs. +func collectLogs(host, container, cursor string, forward bool) (map[string]uint64, string) { + stats := containerdb.NewStatCounter() + newest := "" for { - raw_logs := containerdb.GetLogs(false, true, host, container, "", 1000, until, true, nil) - logs, ok := raw_logs["logs"].([][]string) + page := containerdb.GetLogs(forward, false, host, container, "", 1000, cursor, true, nil) + logs, ok := page["logs"].([][]string) if !ok || len(logs) == 0 { break } - for _, log := range logs { - status_key := containerdb.GetLogStatusKey(log[1]) - calc_stat[status_key]++ - } - - if raw_logs["is_end"].(bool) { - break - } - until = raw_logs["last_processed_key"].(string) - } - - return calc_stat -} - -func collectLogsForward(host, container, since string) (map[string]uint64, string) { - calcStat := map[string]uint64{"error": 0, "debug": 0, "info": 0, "warn": 0, "meta": 0, "other": 0} - - for { - rawLogs := containerdb.GetLogs(true, false, host, container, "", 1000, since, true, nil) - logs, ok := rawLogs["logs"].([][]string) - if !ok || len(logs) == 0 { - break + if !forward && newest == "" { + newest = logs[0][2] } for _, log := range logs { - statusKey := containerdb.GetLogStatusKey(log[1]) - calcStat[statusKey]++ + stats[containerdb.GetLogStatusKey(log[1])]++ } - since = rawLogs["last_processed_key"].(string) - - if rawLogs["is_end"].(bool) { + cursor = page["last_processed_key"].(string) + if page["is_end"].(bool) { break } } - return calcStat, since + + if forward { + return stats, cursor + } + return stats, newest } +// Statistics are keyed by time and read back with time.Parse, so a full log key +// (which carries a " +-" suffix) must be reduced to its timestamp. func saveStats(db *leveldb.DB, stats map[string]uint64, timestamp string) { + key := strings.Split(timestamp, " +")[0] + if _, err := time.Parse(time.RFC3339Nano, key); err != nil { + key = time.Now().UTC().Format(time.RFC3339Nano) + } + to_put, _ := json.Marshal(stats) - db.Put([]byte(timestamp), to_put, nil) + db.Put([]byte(key), to_put, nil) } func resetInMemoryStats(location string) { vars.Mutex.Lock() - vars.Container_Stat_Counter[location] = map[string]uint64{"error": 0, "debug": 0, "info": 0, "warn": 0, "meta": 0, "other": 0} + vars.Container_Stat_Counter[location] = containerdb.NewStatCounter() vars.Mutex.Unlock() } func RunStatisticForContainerWithContext(ctx context.Context, host string, container string) { location := host + "/" + container - vars.Mutex.Lock() - vars.Container_Stat_Counter[location] = map[string]uint64{"error": 0, "debug": 0, "info": 0, "warn": 0, "meta": 0, "other": 0} - vars.Mutex.Unlock() + resetInMemoryStats(location) defer restartStats(host, container) for { select { @@ -128,48 +136,36 @@ func RunStatisticForContainerWithContext(ctx context.Context, host string, conta } } -func RunStatisticForContainer(host string, container string) { - RunStatisticForContainerWithContext(context.Background(), host, container) -} - func GetStatisticsByService(host string, service string, value int) map[string]uint64 { location := host + "/" + service - - vars.Mutex.Lock() - to_return := vars.Container_Stat_Counter[location] - vars.Mutex.Unlock() - - if to_return == nil { - to_return = map[string]uint64{"error": 0, "debug": 0, "info": 0, "warn": 0, "meta": 0, "other": 0} - } + to_return := snapshotCounter(location) if value < 1 { return to_return } searchTo := time.Now().Add(-(time.Hour * time.Duration(value/2))).UTC() - var tmp_stats map[string]uint64 - current_db := util.GetDB(host, service, "statistics") + current_db := util.GetDBIfExists(host, service, "statistics") + if current_db == nil { + return to_return + } iter := current_db.NewIterator(nil, nil) defer iter.Release() iter.Last() - hasPrev := true - result_map := map[string]uint64{"debug": to_return["debug"], "error": to_return["error"], "info": to_return["info"], "warn": to_return["warn"], "meta": to_return["meta"], "other": to_return["other"]} - for hasPrev { + + for hasPrev := true; hasPrev; hasPrev = iter.Prev() { tmp_time, _ := time.Parse(time.RFC3339Nano, string(iter.Key())) if searchTo.After(tmp_time) { break } - json.Unmarshal(iter.Value(), &tmp_stats) - result_map["debug"] += tmp_stats["debug"] - result_map["error"] += tmp_stats["error"] - result_map["info"] += tmp_stats["info"] - result_map["warn"] += tmp_stats["warn"] - result_map["meta"] += tmp_stats["meta"] - result_map["other"] += tmp_stats["other"] - hasPrev = iter.Prev() + // Fresh each round: Unmarshal merges into a non-nil map. + record := map[string]uint64{} + json.Unmarshal(iter.Value(), &record) + for level, count := range record { + to_return[level] += count + } } - return result_map + return to_return } func GetChartData(host string, service string, unit string, uAmount int) map[string]map[string]uint64 { @@ -192,7 +188,11 @@ func GetChartData(host string, service string, unit string, uAmount int) map[str location := host + "/" + service to_return := map[string]map[string]uint64{} - iter := util.GetDB(host, service, "statistics").NewIterator(nil, nil) + statsDB := util.GetDBIfExists(host, service, "statistics") + if statsDB == nil { + return to_return + } + iter := statsDB.NewIterator(nil, nil) iter.Last() defer iter.Release() hasPrev := true @@ -208,23 +208,19 @@ func GetChartData(host string, service string, unit string, uAmount int) map[str } else { datetime = strings.Split(string(iter.Key()), sep)[0] + formatting } - to_return[datetime] = map[string]uint64{"error": 0, "debug": 0, "info": 0, "warn": 0, "meta": 0, "other": 0} - tmp_stats := map[string]uint64{"error": 0, "debug": 0, "info": 0, "warn": 0, "meta": 0, "other": 0} - json.Unmarshal(iter.Value(), &tmp_stats) - - to_return[datetime]["error"] += tmp_stats["error"] - to_return[datetime]["debug"] += tmp_stats["debug"] - to_return[datetime]["info"] += tmp_stats["info"] - to_return[datetime]["warn"] += tmp_stats["warn"] - to_return[datetime]["meta"] += tmp_stats["meta"] - to_return[datetime]["other"] += tmp_stats["other"] + if to_return[datetime] == nil { + to_return[datetime] = containerdb.NewStatCounter() + } + record := map[string]uint64{} + json.Unmarshal(iter.Value(), &record) + for level, count := range record { + to_return[datetime][level] += count + } hasPrev = iter.Prev() } - vars.Mutex.Lock() - to_return["now"] = vars.Container_Stat_Counter[location] - vars.Mutex.Unlock() + to_return["now"] = snapshotCounter(location) return to_return } diff --git a/application/backend/app/statistics/statistics_test.go b/application/backend/app/statistics/statistics_test.go deleted file mode 100644 index 8ac05db..0000000 --- a/application/backend/app/statistics/statistics_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package statistics - -import ( - "encoding/json" - "os" - "strings" - "testing" - "time" - - "github.com/devforth/OnLogs/app/vars" - "github.com/syndtr/goleveldb/leveldb" -) - -func TestRunStatisticForContainer(t *testing.T) { - go RunStatisticForContainer("Test", "TestContainer") - time.Sleep(1 * time.Second) - if vars.Container_Stat_Counter["Test/TestContainer"] == nil { - t.Error("No counter variable for container was created!") - } - if vars.Stat_Containers_DBs["Test/TestContainer"] == nil { - t.Error("DB for stats wasn't created!") - } -} - -func TestGetStatisticsByService(t *testing.T) { - vars.Container_Stat_Counter["test/test"] = map[string]uint64{"error": 1, "debug": 2, "info": 3, "warn": 4, "meta": 0, "other": 5} - os.RemoveAll("leveldb/hosts/test/containers/test/statistics") - statDB, _ := leveldb.OpenFile("leveldb/hosts/test/containers/test/statistics", nil) - to_put, _ := json.Marshal(vars.Container_Stat_Counter["test/test"]) - datetime := strings.Replace(strings.Split(time.Now().UTC().String(), ".")[0], " ", "T", 1) + "Z" - statDB.Put([]byte(datetime), to_put, nil) - statDB.Close() - - res := GetStatisticsByService("test", "test", 2) - if res["debug"] != 4 || res["error"] != 2 || - res["info"] != 6 || res["other"] != 10 || - res["warn"] != 8 { - t.Error("Wrong value!\n", res) - } -} - -func TestGetChartData(t *testing.T) { - cur_db, _ := leveldb.OpenFile("leveldb/hosts/test/statistics", nil) - vars.Container_Stat_Counter["test/test"] = map[string]uint64{"error": 2, "debug": 1, "info": 3, "warn": 5, "meta": 0, "other": 4} - vars.Stat_Containers_DBs["test/test"] = cur_db - to_put, _ := json.Marshal(vars.Container_Stat_Counter["test/test"]) - datetime := strings.Replace(strings.Split(time.Now().UTC().String(), ".")[0], " ", "T", 1) + "Z" - cur_db.Put([]byte(datetime), to_put, nil) - - res := GetChartData("test", "test", "hour", 2) - datetime = datetime[:len(datetime)-6] + "00Z" - if res[datetime]["debug"] != 1 || res[datetime]["error"] != 2 || - res[datetime]["info"] != 3 || res[datetime]["other"] != 4 || - res[datetime]["warn"] != 5 || res["now"]["debug"] != 1 || - res["now"]["error"] != 2 || res["now"]["info"] != 3 || - res["now"]["other"] != 4 || res["now"]["warn"] != 5 { - t.Error("Wrong value!\n", res[datetime]) - } - -} diff --git a/application/backend/app/streamer/streamer.go b/application/backend/app/streamer/streamer.go index bb4a451..2ae1c3a 100644 --- a/application/backend/app/streamer/streamer.go +++ b/application/backend/app/streamer/streamer.go @@ -3,10 +3,7 @@ package streamer import ( "context" "fmt" - "os" - "strconv" "strings" - "sync" "time" "github.com/devforth/OnLogs/app/agent" @@ -19,81 +16,29 @@ import ( type StreamController struct { DaemonService *daemon.DaemonService - - statsMu sync.Mutex - statsCancels map[string]context.CancelFunc -} - -func getStatsWorkerKey(host, container string) string { - return host + "/" + container -} - -func (ctrl *StreamController) registerStatisticsWorker(location string, cancel context.CancelFunc) bool { - ctrl.statsMu.Lock() - defer ctrl.statsMu.Unlock() - if ctrl.statsCancels == nil { - ctrl.statsCancels = map[string]context.CancelFunc{} - } - if _, exists := ctrl.statsCancels[location]; exists { - return false - } - ctrl.statsCancels[location] = cancel - return true -} - -func (ctrl *StreamController) unregisterStatisticsWorker(location string) (context.CancelFunc, bool) { - ctrl.statsMu.Lock() - defer ctrl.statsMu.Unlock() - cancel, exists := ctrl.statsCancels[location] - if exists { - delete(ctrl.statsCancels, location) - } - return cancel, exists -} - -func (ctrl *StreamController) ensureStatisticsWorker(ctx context.Context, host, container string) { - location := getStatsWorkerKey(host, container) - workerCtx, cancel := context.WithCancel(ctx) - if !ctrl.registerStatisticsWorker(location, cancel) { - cancel() - return - } - go statistics.RunStatisticForContainerWithContext(workerCtx, host, container) -} - -func (ctrl *StreamController) stopStatisticsWorker(host, container string) { - cancel, exists := ctrl.unregisterStatisticsWorker(getStatsWorkerKey(host, container)) - if exists { - cancel() - } -} - -func (ctrl *StreamController) statisticsWorkersCount() int { - ctrl.statsMu.Lock() - defer ctrl.statsMu.Unlock() - return len(ctrl.statsCancels) } func (ctrl *StreamController) ensureStreams(ctx context.Context, containers []string) { host := util.GetHost() for _, container := range containers { - ctrl.ensureStatisticsWorker(ctx, host, container) + statistics.EnsureWorker(ctx, host, container) ctrl.DaemonService.EnsureStream(ctx, container) } } func (ctrl *StreamController) reconcileStreams(ctx context.Context) { + containers := vars.DockerContainerList() current := map[string]struct{}{} - for _, container := range vars.DockerContainers { + for _, container := range containers { current[container] = struct{}{} } - ctrl.ensureStreams(ctx, vars.DockerContainers) + ctrl.ensureStreams(ctx, containers) - for _, active := range append([]string{}, vars.Active_Daemon_Streams...) { + for _, active := range vars.ActiveStreams() { if _, exists := current[active]; !exists { ctrl.DaemonService.StopStream(active) - ctrl.stopStatisticsWorker(util.GetHost(), active) + statistics.StopWorker(util.GetHost(), active) } } } @@ -106,16 +51,14 @@ func (ctrl *StreamController) handleContainerEvent(ctx context.Context, msg even switch msg.Action { case "start", "restart", "unpause": - if !util.Contains(containerName, vars.DockerContainers) { - vars.DockerContainers = append(vars.DockerContainers, containerName) - } - ctrl.ensureStatisticsWorker(ctx, util.GetHost(), containerName) + vars.AddDockerContainer(containerName) + statistics.EnsureWorker(ctx, util.GetHost(), containerName) ctrl.DaemonService.EnsureStream(ctx, containerName) case "die", "stop", "pause": ctrl.DaemonService.StopStream(containerName) case "destroy": ctrl.DaemonService.StopStream(containerName) - ctrl.stopStatisticsWorker(util.GetHost(), containerName) + statistics.StopWorker(util.GetHost(), containerName) } } @@ -157,15 +100,15 @@ func (ctrl *StreamController) startEventsLoop(ctx context.Context) { } func (ctrl *StreamController) StreamLogs(ctx context.Context) { - if vars.FavsDBErr != nil || vars.StateDBErr != nil || vars.UsersDBErr != nil { - fmt.Println("ERROR: unable to open leveldb", vars.FavsDBErr, vars.StateDBErr, vars.UsersDBErr) + if vars.FavsDBErr != nil || vars.UsersDBErr != nil { + fmt.Println("ERROR: unable to open leveldb", vars.FavsDBErr, vars.UsersDBErr) return } - vars.DockerContainers = ctrl.DaemonService.GetContainersList(ctx) + vars.SetDockerContainers(ctrl.DaemonService.GetContainersList(ctx)) ctrl.reconcileStreams(ctx) - if os.Getenv("AGENT") != "" { - agent.SendInitRequest(vars.DockerContainers) + if util.IsAgentMode() { + agent.SendInitRequest(vars.DockerContainerList()) } go ctrl.startEventsLoop(ctx) @@ -178,11 +121,10 @@ func (ctrl *StreamController) StreamLogs(ctx context.Context) { case <-ctx.Done(): return case <-reconcileTicker.C: - vars.Year = strconv.Itoa(time.Now().UTC().Year()) - vars.DockerContainers = ctrl.DaemonService.GetContainersList(ctx) + vars.SetDockerContainers(ctrl.DaemonService.GetContainersList(ctx)) ctrl.reconcileStreams(ctx) - if os.Getenv("AGENT") != "" { - agent.SendUpdate(vars.DockerContainers) + if util.IsAgentMode() { + agent.SendUpdate(vars.DockerContainerList()) agent.TryResend() } } diff --git a/application/backend/app/streamer/streamer_test.go b/application/backend/app/streamer/streamer_test.go deleted file mode 100644 index 3d83039..0000000 --- a/application/backend/app/streamer/streamer_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package streamer - -import ( - "context" - "fmt" - "testing" -) - -func TestRegisterStatisticsWorkerNoDuplicates(t *testing.T) { - ctrl := &StreamController{} - location := getStatsWorkerKey("host", "container") - - first := ctrl.registerStatisticsWorker(location, func() {}) - second := ctrl.registerStatisticsWorker(location, func() {}) - - if !first { - t.Fatal("first registration must succeed") - } - if second { - t.Fatal("duplicate registration must be rejected") - } - if ctrl.statisticsWorkersCount() != 1 { - t.Fatalf("expected exactly one worker, got %d", ctrl.statisticsWorkersCount()) - } -} - -func TestStatisticsWorkersLongChurnDoesNotLeak(t *testing.T) { - ctrl := &StreamController{} - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - host := "churn-host" - for i := 0; i < 300; i++ { - container := fmt.Sprintf("ephemeral-%d", i) - ctrl.ensureStatisticsWorker(ctx, host, container) - ctrl.stopStatisticsWorker(host, container) - } - - if ctrl.statisticsWorkersCount() != 0 { - t.Fatalf("expected zero workers after churn, got %d", ctrl.statisticsWorkersCount()) - } -} diff --git a/application/backend/app/userdb/password.go b/application/backend/app/userdb/password.go new file mode 100644 index 0000000..0b8f7a7 --- /dev/null +++ b/application/backend/app/userdb/password.go @@ -0,0 +1,58 @@ +package userdb + +import ( + "crypto/pbkdf2" + "crypto/rand" + "crypto/sha256" + "crypto/subtle" + "encoding/base64" + "strconv" + "strings" +) + +const ( + hashScheme = "pbkdf2_sha256" + hashIterations = 600000 + hashKeyLength = 32 + hashSaltLength = 16 +) + +func HashPassword(password string) string { + salt := make([]byte, hashSaltLength) + if _, err := rand.Read(salt); err != nil { + panic(err) + } + return encodeHash(password, salt, hashIterations) +} + +func encodeHash(password string, salt []byte, iterations int) string { + key, err := pbkdf2.Key(sha256.New, password, salt, iterations, hashKeyLength) + if err != nil { + panic(err) + } + return strings.Join([]string{ + hashScheme, + strconv.Itoa(iterations), + base64.RawStdEncoding.EncodeToString(salt), + base64.RawStdEncoding.EncodeToString(key), + }, "$") +} + +func verifyHash(stored string, password string) (ok bool, wasHashed bool) { + parts := strings.Split(stored, "$") + if len(parts) != 4 || parts[0] != hashScheme { + return false, false + } + + iterations, err := strconv.Atoi(parts[1]) + if err != nil || iterations <= 0 { + return false, true + } + salt, err := base64.RawStdEncoding.DecodeString(parts[2]) + if err != nil { + return false, true + } + + candidate := encodeHash(password, salt, iterations) + return subtle.ConstantTimeCompare([]byte(candidate), []byte(stored)) == 1, true +} diff --git a/application/backend/app/userdb/password_test.go b/application/backend/app/userdb/password_test.go new file mode 100644 index 0000000..bf8b56a --- /dev/null +++ b/application/backend/app/userdb/password_test.go @@ -0,0 +1,85 @@ +package userdb + +import ( + "strings" + "testing" + + "github.com/devforth/OnLogs/app/vars" +) + +func TestCheckUserPasswordRejectsAnEmptyPassword(t *testing.T) { + if err := vars.UsersDB.Put([]byte("emptypwuser"), []byte(""), nil); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { vars.UsersDB.Delete([]byte("emptypwuser"), nil) }) + + if CheckUserPassword("emptypwuser", "") { + t.Fatal("a user stored with an empty password authenticated with an empty password") + } +} + +func TestCheckUserPasswordRejectsUnknownUser(t *testing.T) { + if CheckUserPassword("no-such-user-at-all", "") { + t.Fatal("unknown user authenticated with an empty password") + } + if CheckUserPassword("no-such-user-at-all", "anything") { + t.Fatal("unknown user authenticated") + } +} + +func TestStoredPasswordsAreNotPlaintext(t *testing.T) { + const secret = "correct horse battery staple" + CreateUser("hasheduser", secret) + t.Cleanup(func() { vars.UsersDB.Delete([]byte("hasheduser"), nil) }) + + stored, err := vars.UsersDB.Get([]byte("hasheduser"), nil) + if err != nil { + t.Fatal(err) + } + if strings.Contains(string(stored), secret) { + t.Fatalf("the password is stored in cleartext: %q", stored) + } + if !CheckUserPassword("hasheduser", secret) { + t.Fatal("the correct password no longer verifies") + } + if CheckUserPassword("hasheduser", secret+"x") { + t.Fatal("a wrong password verifies") + } +} + +func TestEditUserStoresAHash(t *testing.T) { + CreateUser("edithashuser", "first-password") + t.Cleanup(func() { vars.UsersDB.Delete([]byte("edithashuser"), nil) }) + + EditUser("edithashuser", "second-password") + + stored, _ := vars.UsersDB.Get([]byte("edithashuser"), nil) + if strings.Contains(string(stored), "second-password") { + t.Fatalf("EditUser stored the password in cleartext: %q", stored) + } + if !CheckUserPassword("edithashuser", "second-password") { + t.Fatal("the new password does not verify") + } + if CheckUserPassword("edithashuser", "first-password") { + t.Fatal("the old password still verifies") + } +} + +func TestLegacyPlaintextPasswordVerifiesAndIsUpgraded(t *testing.T) { + if err := vars.UsersDB.Put([]byte("legacyuser"), []byte("legacy-secret"), nil); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { vars.UsersDB.Delete([]byte("legacyuser"), nil) }) + + if !CheckUserPassword("legacyuser", "legacy-secret") { + t.Fatal("an account created before hashing stopped working") + } + + stored, _ := vars.UsersDB.Get([]byte("legacyuser"), nil) + if string(stored) == "legacy-secret" { + t.Fatal("a verified legacy password was not upgraded to a hash") + } + if !CheckUserPassword("legacyuser", "legacy-secret") { + t.Fatal("the password stopped verifying after the upgrade") + } +} diff --git a/application/backend/app/userdb/userdb.go b/application/backend/app/userdb/userdb.go index 6e7c862..211d3a2 100644 --- a/application/backend/app/userdb/userdb.go +++ b/application/backend/app/userdb/userdb.go @@ -1,10 +1,10 @@ package userdb import ( + "crypto/subtle" "encoding/json" "errors" "os" - "strings" "github.com/devforth/OnLogs/app/vars" ) @@ -19,57 +19,65 @@ func CreateUser(login string, password string) error { return errors.New("User is already exists") } - vars.UsersDB.Put([]byte(login), []byte(password), nil) - return nil + return vars.UsersDB.Put([]byte(login), []byte(HashPassword(password)), nil) } func GetUsers() []map[string]interface{} { var users []map[string]interface{} iter := vars.UsersDB.NewIterator(nil, nil) + defer iter.Release() + for iter.Next() { - var editable bool - if string(iter.Key()) == os.Getenv("ADMIN_USERNAME") { - editable = false - } else { - editable = true - } - - user := map[string]interface{}{ + users = append(users, map[string]interface{}{ "username": string(iter.Key()), - "editable": editable, - } - users = append(users, user) + "editable": string(iter.Key()) != os.Getenv("ADMIN_USERNAME"), + }) } - defer iter.Release() - return users } -func EditUser(login string, password string) { - vars.UsersDB.Put([]byte(login), []byte(password), nil) +func EditUser(login string, password string) error { + return vars.UsersDB.Put([]byte(login), []byte(HashPassword(password)), nil) } -func DeleteUser(login string, password string) error { +func DeleteUser(login string) error { isExists, _ := vars.UsersDB.Has([]byte(login), nil) if !isExists { return errors.New("No such user") } - vars.UsersDB.Delete([]byte(login), nil) - return nil + return vars.UsersDB.Delete([]byte(login), nil) } func CheckUserPassword(login string, gotPassword string) bool { - password, err := vars.UsersDB.Get([]byte(login), nil) - if err != nil || strings.Compare(string(password), gotPassword) != 0 { + // goleveldb returns ([]byte{}, nil) for a key stored with an empty value. + if login == "" || gotPassword == "" { return false } + stored, err := vars.UsersDB.Get([]byte(login), nil) + if err != nil || len(stored) == 0 { + return false + } + + if ok, wasHashed := verifyHash(string(stored), gotPassword); wasHashed { + return ok + } + + // Accounts predating hashing hold the password verbatim; verify, then upgrade. + if subtle.ConstantTimeCompare(stored, []byte(gotPassword)) != 1 { + return false + } + vars.UsersDB.Put([]byte(login), []byte(HashPassword(gotPassword)), nil) return true } func GetUserSettings(username string) map[string]interface{} { var to_return map[string]interface{} + if vars.SettingsDB == nil { + return to_return + } + vars.Mutex.Lock() result, _ := vars.SettingsDB.Get([]byte(username), nil) vars.Mutex.Unlock() @@ -77,9 +85,16 @@ func GetUserSettings(username string) map[string]interface{} { return to_return } -func UpdateUserSettings(username string, settings map[string]interface{}) { - to_put, _ := json.Marshal(settings) +func UpdateUserSettings(username string, settings map[string]interface{}) error { + to_put, err := json.Marshal(settings) + if err != nil { + return err + } + if vars.SettingsDB == nil { + return errors.New("settings database is unavailable") + } + vars.Mutex.Lock() - vars.SettingsDB.Put([]byte(username), to_put, nil) - vars.Mutex.Unlock() + defer vars.Mutex.Unlock() + return vars.SettingsDB.Put([]byte(username), to_put, nil) } diff --git a/application/backend/app/userdb/userdb_test.go b/application/backend/app/userdb/userdb_test.go index 9ae9ed3..115725e 100644 --- a/application/backend/app/userdb/userdb_test.go +++ b/application/backend/app/userdb/userdb_test.go @@ -39,19 +39,22 @@ func TestEditUser(t *testing.T) { CreateUser("testtest", "testtest") EditUser("testtest", "sus?") - pass, _ := vars.UsersDB.Get([]byte("testtest"), nil) - if string(pass) != "sus?" { + if !CheckUserPassword("testtest", "sus?") { t.Error("User wasn't edited") } + pass, _ := vars.UsersDB.Get([]byte("testtest"), nil) + if string(pass) == "sus?" { + t.Error("Password is stored in cleartext") + } } func TestDeleteUser(t *testing.T) { - err := DeleteUser("aaaaaaaaa????????", "123") + err := DeleteUser("aaaaaaaaa????????") if err == nil { t.Error("Error is nil") } - DeleteUser("admin1", "admin") + DeleteUser("admin1") if IsUserExists("admin1") { t.Error("User should be deleted") } diff --git a/application/backend/app/util/agentmode_test.go b/application/backend/app/util/agentmode_test.go new file mode 100644 index 0000000..21729f0 --- /dev/null +++ b/application/backend/app/util/agentmode_test.go @@ -0,0 +1,46 @@ +package util + +import ( + "os" + "testing" +) + +func TestIsAgentModeTreatsTheValueAsABoolean(t *testing.T) { + cases := map[string]bool{ + "": false, + "false": false, + "FALSE": false, + "0": false, + "no": false, + "nonsense": false, + "true": true, + "TRUE": true, + "1": true, + } + + for value, want := range cases { + os.Setenv("AGENT", value) + if got := IsAgentMode(); got != want { + t.Errorf("AGENT=%q: agent mode is %v, want %v", value, got, want) + } + } + os.Unsetenv("AGENT") +} + +func TestParseHostnameHandlesAnEmptyFile(t *testing.T) { + if host := parseHostname("", nil); host == "" { + t.Error("an empty /etc/hostname produced an empty host, which indexes out of range downstream") + } + if host := parseHostname("\n", nil); host == "" { + t.Error("a newline-only /etc/hostname produced an empty host") + } + if host := parseHostname("myhost\n", nil); host != "myhost" { + t.Errorf("trailing newline not stripped: %q", host) + } + if host := parseHostname("myhost\r\n", nil); host != "myhost" { + t.Errorf("trailing CRLF not stripped: %q", host) + } + if host := parseHostname("myhost", nil); host != "myhost" { + t.Errorf("a clean hostname was altered: %q", host) + } +} diff --git a/application/backend/app/util/inituser_test.go b/application/backend/app/util/inituser_test.go new file mode 100644 index 0000000..fb4367b --- /dev/null +++ b/application/backend/app/util/inituser_test.go @@ -0,0 +1,30 @@ +package util + +import ( + "os" + "testing" + + "github.com/devforth/OnLogs/app/vars" +) + +func TestCreateInitUserRefusesAnEmptyAdminPassword(t *testing.T) { + const probe = "admin-empty-pw-probe" + os.Setenv("ADMIN_USERNAME", probe) + os.Setenv("ADMIN_PASSWORD", "") + t.Cleanup(func() { + vars.UsersDB.Delete([]byte(probe), nil) + os.Setenv("ADMIN_USERNAME", "admin") + os.Setenv("ADMIN_PASSWORD", "") + }) + + CreateInitUser() + + exists, err := vars.UsersDB.Has([]byte(probe), nil) + if err != nil { + t.Fatal(err) + } + if exists { + stored, _ := vars.UsersDB.Get([]byte(probe), nil) + t.Fatalf("admin was created with an empty ADMIN_PASSWORD (stored value %q)", stored) + } +} diff --git a/application/backend/app/util/jwt_test.go b/application/backend/app/util/jwt_test.go new file mode 100644 index 0000000..9ad03bf --- /dev/null +++ b/application/backend/app/util/jwt_test.go @@ -0,0 +1,129 @@ +package util + +import ( + "net/http" + "os" + "testing" + "time" + + "github.com/devforth/OnLogs/app/vars" + "github.com/golang-jwt/jwt/v5" +) + +func requestWithCookie(value string) http.Request { + req, _ := http.NewRequest("GET", "", nil) + req.AddCookie(&http.Cookie{Name: "onlogs-cookie", Value: value}) + return *req +} + +func TestGetUserFromJWTRejectsUnsignedTokens(t *testing.T) { + os.Setenv("JWT_SECRET", "a-real-secret-value-for-the-test") + + token := jwt.NewWithClaims(jwt.SigningMethodNone, jwt.MapClaims{ + "user": "admin", + "authorized": true, + "exp": time.Now().Add(time.Hour).Unix(), + }) + unsigned, err := token.SignedString(jwt.UnsafeAllowNoneSignatureType) + if err != nil { + t.Fatal(err) + } + + user, err := GetUserFromJWT(requestWithCookie(unsigned)) + if err == nil { + t.Fatalf("alg=none token accepted as user %q", user) + } +} + +func TestGetUserFromJWTRejectsTokenWithoutExpiry(t *testing.T) { + secret := "a-real-secret-value-for-the-test" + os.Setenv("JWT_SECRET", secret) + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "user": "admin", + "authorized": true, + }) + signed, err := token.SignedString([]byte(secret)) + if err != nil { + t.Fatal(err) + } + + user, err := GetUserFromJWT(requestWithCookie(signed)) + if err == nil { + t.Fatalf("token without exp accepted as user %q", user) + } +} + +func TestGetUserFromJWTRejectsTokenWithoutUser(t *testing.T) { + secret := "a-real-secret-value-for-the-test" + os.Setenv("JWT_SECRET", secret) + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "authorized": true, + "exp": time.Now().Add(time.Hour).Unix(), + }) + signed, err := token.SignedString([]byte(secret)) + if err != nil { + t.Fatal(err) + } + + if user, err := GetUserFromJWT(requestWithCookie(signed)); err == nil { + t.Fatalf("token without a user claim accepted as %q", user) + } +} + +func TestGetUserFromJWTRejectsEverythingWhenTheSecretIsEmpty(t *testing.T) { + os.Setenv("JWT_SECRET", "") + t.Cleanup(func() { os.Setenv("JWT_SECRET", "1231efdZF") }) + + forged := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "user": "admin", + "authorized": true, + "exp": time.Now().Add(time.Hour).Unix(), + }) + signed, err := forged.SignedString([]byte("")) + if err != nil { + t.Fatal(err) + } + + if user, err := GetUserFromJWT(requestWithCookie(signed)); err == nil { + t.Fatalf("cookie forged with an empty key authenticated as %q", user) + } +} + +func TestGenerateJWTSecretIsNotPredictable(t *testing.T) { + seen := map[string]bool{} + for i := 0; i < 64; i++ { + s := GenerateJWTSecret() + if len(s) < 25 { + t.Fatalf("token too short: %q", s) + } + if seen[s] { + t.Fatalf("duplicate token generated: %q", s) + } + seen[s] = true + } +} + +func TestGetUserFromJWTRejectsADeletedAccount(t *testing.T) { + secret := "a-real-secret-value-for-the-test" + os.Setenv("JWT_SECRET", secret) + + login := "about-to-be-deleted" + if err := vars.UsersDB.Put([]byte(login), []byte("irrelevant"), nil); err != nil { + t.Fatal(err) + } + + signed := CreateJWT(login) + if user, err := GetUserFromJWT(requestWithCookie(signed)); err != nil || user != login { + t.Fatalf("the token should work while the account exists: %q %v", user, err) + } + + if err := vars.UsersDB.Delete([]byte(login), nil); err != nil { + t.Fatal(err) + } + + if user, err := GetUserFromJWT(requestWithCookie(signed)); err == nil { + t.Fatalf("a deleted account still authenticates as %q; deleting a user revokes nothing", user) + } +} diff --git a/application/backend/app/util/safename_test.go b/application/backend/app/util/safename_test.go new file mode 100644 index 0000000..386524a --- /dev/null +++ b/application/backend/app/util/safename_test.go @@ -0,0 +1,108 @@ +package util + +import ( + "os" + "testing" +) + +func TestGetDBRefusesNamesThatLeaveTheTree(t *testing.T) { + t.Chdir(t.TempDir()) + + cases := [][3]string{ + {"/", "c", "logs"}, + {"c", "/", "logs"}, + {"c", "c", "/"}, + {"a\\b", "c", "logs"}, + {"../../../PWN", "c", "logs"}, + {"realhost", "../../../../PWN", "logs"}, + {"realhost", "c", "../../../PWN"}, + {"", "c", "logs"}, + {"realhost", "", "logs"}, + {".", "c", "logs"}, + {"..", "c", "logs"}, + {"a/b", "c", "logs"}, + } + + for _, c := range cases { + if db := GetDB(c[0], c[1], c[2]); db != nil { + t.Errorf("GetDB(%q, %q, %q) opened a database", c[0], c[1], c[2]) + } + } + + if _, err := os.Stat("PWN"); err == nil { + t.Fatal("GetDB created a directory outside leveldb/hosts") + } + if entries, err := os.ReadDir("."); err == nil { + for _, e := range entries { + if e.Name() != "leveldb" { + t.Errorf("unexpected entry created outside the tree: %s", e.Name()) + } + } + } +} + +func TestGetDBStillOpensLegitimateNames(t *testing.T) { + t.Chdir(t.TempDir()) + + db := GetDB("somehost", "somecontainer", "logs") + if db == nil { + t.Fatal("GetDB refused a legitimate host/container/dbType") + } + db.Close() + + if _, err := os.Stat("leveldb/hosts/somehost/containers/somecontainer/logs"); err != nil { + t.Fatalf("database was not created where expected: %v", err) + } +} + +func TestGetDirSizeRefusesNamesThatLeaveTheTree(t *testing.T) { + t.Chdir(t.TempDir()) + + if err := os.MkdirAll("leveldb/hosts/realhost/containers", 0o700); err != nil { + t.Fatal(err) + } + if err := os.MkdirAll("outside", 0o700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile("outside/big", make([]byte, 512*1024), 0o600); err != nil { + t.Fatal(err) + } + + if size := GetDirSize("realhost", "../../../../outside"); size != 0 { + t.Fatalf("GetDirSize measured a directory outside the tree: %v MiB", size) + } +} + +func TestGetDockerContainerIDRefusesNamesThatLeaveTheTree(t *testing.T) { + t.Chdir(t.TempDir()) + + if err := os.MkdirAll("leveldb/hosts", 0o700); err != nil { + t.Fatal(err) + } + + id := GetDockerContainerID("../..", "anything") + if id != "" { + t.Errorf("GetDockerContainerID accepted a traversing host: %q", id) + } + if _, err := os.Stat("containersMeta"); err == nil { + t.Fatal("GetDockerContainerID created a LevelDB outside leveldb/hosts") + } +} + +func TestIsSafeNameRejectsEverySeparatorShape(t *testing.T) { + unsafe := []string{ + "", ".", "..", "/", "//", "a/", "/a", "a/b", "../x", "x/..", + "a\\b", "\\", "a\x00b", + } + for _, name := range unsafe { + if IsSafeName(name) { + t.Errorf("IsSafeName(%q) accepted a name that is not a single path component", name) + } + } + + for _, name := range []string{"ok", "my-container", "my_container.1", "a"} { + if !IsSafeName(name) { + t.Errorf("IsSafeName(%q) rejected a legitimate name", name) + } + } +} diff --git a/application/backend/app/util/util.go b/application/backend/app/util/util.go index 9de4e09..2f51856 100644 --- a/application/backend/app/util/util.go +++ b/application/backend/app/util/util.go @@ -2,10 +2,10 @@ package util import ( "bytes" + "crypto/rand" "errors" "fmt" "io/fs" - "math/rand" "net/http" "os" "path/filepath" @@ -13,6 +13,7 @@ import ( "strings" "time" + "github.com/devforth/OnLogs/app/userdb" "github.com/devforth/OnLogs/app/vars" "github.com/golang-jwt/jwt/v5" "github.com/syndtr/goleveldb/leveldb" @@ -36,22 +37,19 @@ func replaceVarForAllFilesInDir(dirName string, dir_files []fs.DirEntry) { } } -func Contains(a string, list []string) bool { - for _, b := range list { - if strings.Compare(b, a) == 0 { - return true - } - } - return false -} - -func CreateInitUser() { +func CreateInitUser() error { admin_username := os.Getenv("ADMIN_USERNAME") if admin_username == "" { admin_username = "admin" os.Setenv("ADMIN_USERNAME", admin_username) } - vars.UsersDB.Put([]byte(admin_username), []byte(os.Getenv("ADMIN_PASSWORD")), nil) + + admin_password := os.Getenv("ADMIN_PASSWORD") + if admin_password == "" { + return errors.New("ADMIN_PASSWORD is empty; refusing to create an administrator that would accept an empty password") + } + + return vars.UsersDB.Put([]byte(admin_username), []byte(userdb.HashPassword(admin_password)), nil) } func ReplacePrefixVariableForFrontend() { @@ -73,14 +71,30 @@ func CreateJWT(login string) string { token := jwt.New(jwt.SigningMethodHS256) claims := token.Claims.(jwt.MapClaims) claims["exp"] = time.Now().AddDate(0, 0, 2).Unix() - claims["authorized"] = true claims["user"] = login tokenString, _ := token.SignedString([]byte(os.Getenv("JWT_SECRET"))) return tokenString } +// Every path component must be a single, literal name; anything else escapes +// leveldb/hosts. +func IsSafeName(s string) bool { + if s == "" || s == "." || s == ".." { + return false + } + // filepath.Base("/") is "/", so the Base comparison alone lets it through. + if strings.ContainsAny(s, `/\`) || strings.ContainsRune(s, 0) { + return false + } + return s == filepath.Base(s) +} + func GetDB(host string, container string, dbType string) *leveldb.DB { + if !IsSafeName(host) || !IsSafeName(container) || !IsSafeName(dbType) { + return nil + } + vars.DBMutex.RLock() db := getExistingDB(host, container, dbType) vars.DBMutex.RUnlock() @@ -111,66 +125,138 @@ func GetDB(host string, container string, dbType string) *leveldb.DB { } if err != nil { - panic(fmt.Sprintf("ERROR: unable to open db for %s/%s/%s\n%v", - host, container, dbType, err)) - } - - switch dbType { - case "logs": - vars.ActiveDBs[container] = db - case "statistics": - vars.Stat_Containers_DBs[host+"/"+container] = db - case "hosts_statistics": - vars.Stat_Hosts_DBs[host] = db - case "statuses": - vars.Statuses_DBs[host+"/"+container] = db - case "brokenlogs": - vars.BrokenLogs_DBs[container] = db - case "containersmeta": - vars.ContainersMeta_DBs[host+"/"+container] = db - case "streamstate": - vars.StreamState_DBs[host+"/"+container] = db + fmt.Printf("ERROR: unable to open db for %s/%s/%s: %v\n", host, container, dbType, err) + return nil } + // Assigning into a nil map panics, unlike reading or deleting. + if cache := dbCaches[dbType]; cache != nil { + cache[host+"/"+container] = db + } return db } -func getExistingDB(host, container, dbType string) *leveldb.DB { - switch dbType { - case "logs": - return vars.ActiveDBs[container] - case "statistics": - return vars.Stat_Containers_DBs[host+"/"+container] - case "hosts_statistics": - return vars.Stat_Hosts_DBs[host] - case "statuses": - return vars.Statuses_DBs[host+"/"+container] - case "brokenlogs": - return vars.BrokenLogs_DBs[container] - case "containersmeta": - return vars.ContainersMeta_DBs[host+"/"+container] - case "streamstate": - return vars.StreamState_DBs[host+"/"+container] +// GetDBIfExists is the read path: it never creates. GetDB opens-or-creates and +// caches forever. +func GetDBIfExists(host string, container string, dbType string) *leveldb.DB { + if !IsSafeName(host) || !IsSafeName(container) { + return nil } - return nil + if info, err := os.Stat("leveldb/hosts/" + host + "/containers/" + container); err != nil || !info.IsDir() { + return nil + } + return GetDB(host, container, dbType) } -func GetHost() string { - hostname, err := os.ReadFile("/etc/hostname") - var host string +func GetContainersMetaDB(host string) *leveldb.DB { + if !IsSafeName(host) { + return nil + } + + vars.DBMutex.RLock() + db := vars.ContainersMeta_DBs[host] + vars.DBMutex.RUnlock() + if db != nil { + return db + } + + vars.DBMutex.Lock() + defer vars.DBMutex.Unlock() + + if db = vars.ContainersMeta_DBs[host]; db != nil { + return db + } + + db, err := leveldb.OpenFile("leveldb/hosts/"+host+"/containersMeta", nil) if err != nil { - host, _ = os.Hostname() - } else { - host = string(hostname) + fmt.Printf("ERROR: unable to open containersMeta for %s: %v\n", host, err) + return nil + } + vars.ContainersMeta_DBs[host] = db + return db +} + +func ResetDB(host string, container string, dbType string) { + if !IsSafeName(host) || !IsSafeName(container) || !IsSafeName(dbType) { + return + } + + vars.DBMutex.Lock() + defer vars.DBMutex.Unlock() + + if db := getExistingDB(host, container, dbType); db != nil { + db.Close() + } + delete(dbCaches[dbType], host+"/"+container) +} + +// ContainersMeta_DBs is absent: GetContainersMetaDB keys it by bare host. +var dbCaches = map[string]map[string]*leveldb.DB{ + "logs": vars.ActiveDBs, + "statistics": vars.Stat_Containers_DBs, + "statuses": vars.Statuses_DBs, + "brokenlogs": vars.BrokenLogs_DBs, + "streamstate": vars.StreamState_DBs, +} + +func getExistingDB(host, container, dbType string) *leveldb.DB { + return dbCaches[dbType][host+"/"+container] +} + +// AGENT is documented as a boolean, so "false" must mean off. +func IsAgentMode() bool { + enabled, err := strconv.ParseBool(os.Getenv("AGENT")) + return err == nil && enabled +} + +func parseHostname(raw string, readErr error) string { + if readErr != nil { + fallback, _ := os.Hostname() + raw = fallback } - if host[len(host)-1] < 32 || host[len(host)-1] > 126 { - host = host[:len(host)-1] + host := strings.TrimFunc(raw, func(r rune) bool { return r < 32 || r > 126 }) + if host == "" { + if fallback, err := os.Hostname(); err == nil { + host = strings.TrimSpace(fallback) + } + } + if host == "" { + host = "localhost" } return host } +func GetHost() string { + hostname, err := os.ReadFile("/etc/hostname") + return parseHostname(string(hostname), err) +} + +// LogsSizes reports bytes per host/container plus the total. The only walk of +// the logs tree, so the size a user sees and the size the quota compares against +// cannot drift apart. One filepath.Walk per container: never call it on a +// request that runs often. +func LogsSizes() (map[string]int64, int64) { + perContainer := map[string]int64{} + var total int64 + + hosts, _ := os.ReadDir("leveldb/hosts/") + for _, host := range hosts { + containers, _ := os.ReadDir("leveldb/hosts/" + host.Name() + "/containers") + for _, container := range containers { + bytes := int64(GetDirSize(host.Name(), container.Name()) * 1024 * 1024) + perContainer[host.Name()+"/"+container.Name()] = bytes + total += bytes + } + } + return perContainer, total +} + func GetDirSize(host string, container string) float64 { + if !IsSafeName(host) || !IsSafeName(container) { + return 0 + } + var size int64 path := "leveldb/hosts/" + host + "/containers/" + container @@ -191,59 +277,96 @@ func GetDirSize(host string, container string) float64 { return float64(size) / (1024.0 * 1024.0) } +// prunableDBs are the sub-databases retention actually deletes from. Measuring +// anything else makes the quota unreachable: retention would strip these to +// nothing trying to offset data it cannot touch. +var prunableDBs = []string{"logs", "statuses", "statistics"} + +func GetPrunableSize(host string, container string) float64 { + if !IsSafeName(host) || !IsSafeName(container) { + return 0 + } + + var size int64 + for _, dbType := range prunableDBs { + path := "leveldb/hosts/" + host + "/containers/" + container + "/" + dbType + filepath.Walk(path, func(_ string, info os.FileInfo, err error) error { + if err != nil { + return nil + } + if info != nil && !info.IsDir() { + size += info.Size() + } + return nil + }) + } + return float64(size) / (1024.0 * 1024.0) +} + +func PrunableDBs() []string { + return append([]string{}, prunableDBs...) +} + func GetUserFromJWT(req http.Request) (string, error) { c, _ := req.Cookie("onlogs-cookie") if c == nil { return "", errors.New("401 - Unauthorized!") } + // An empty key verifies every HMAC token. + secret := os.Getenv("JWT_SECRET") + if secret == "" { + return "", errors.New("401 - Unauthorized!") + } + claims := jwt.MapClaims{} _, err := jwt.ParseWithClaims(c.Value, claims, func(token *jwt.Token) (interface{}, error) { - return []byte(os.Getenv("JWT_SECRET")), nil - }) + return []byte(secret), nil + }, jwt.WithValidMethods([]string{jwt.SigningMethodHS256.Alg()}), jwt.WithExpirationRequired()) - if err != nil && strings.Compare(err.Error(), "Token is expired") != 0 { + if err != nil { return "", err } - if int64(int64(claims["exp"].(float64))) < time.Now().Unix() { + exp, ok := claims["exp"].(float64) + if !ok { + return "", errors.New("Token is expired") + } + if int64(exp) < time.Now().Unix() { return "", errors.New("Token is expired") } - return claims["user"].(string), nil -} - -func GenerateJWTSecret() string { - tokenLen := 25 - - letterBytes := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_." - b := make([]byte, tokenLen) + user, ok := claims["user"].(string) + if !ok || user == "" { + return "", errors.New("401 - Unauthorized!") + } - s1 := rand.NewSource(time.Now().UnixNano()) - r1 := rand.New(s1) - for i := range b { - b[i] = letterBytes[r1.Int63()%int64(len(letterBytes))] + // A valid signature is not enough: deleting an account must revoke it. + if exists, err := vars.UsersDB.Has([]byte(user), nil); err != nil || !exists { + return "", errors.New("401 - Unauthorized!") } - token := string(b) + return user, nil +} - return token +// Mints agent ingestion tokens, so it must be cryptographically random. +func GenerateJWTSecret() string { + return rand.Text() } func GetDockerContainerID(host string, container string) string { + if !IsSafeName(host) { + return "" + } + _, err := os.ReadDir("leveldb/hosts/" + host) if err != nil { return "" } - containersMetaDB := vars.ContainersMeta_DBs[host] + containersMetaDB := GetContainersMetaDB(host) if containersMetaDB == nil { - containersMetaDB, err := leveldb.OpenFile("leveldb/hosts/"+host+"/containersMeta", nil) - if err != nil { - panic(err) - } - vars.ContainersMeta_DBs[host] = containersMetaDB + return "" } - containersMetaDB = vars.ContainersMeta_DBs[host] iter := containersMetaDB.NewIterator(nil, nil) defer iter.Release() @@ -261,7 +384,7 @@ func GetDockerContainerID(host string, container string) string { func DeleteDockerLogs(host string, container string) error { if host != GetHost() { - vars.ToDelete[host] = append(vars.ToDelete[host+"/"+container], container) + vars.QueueDelete(host, container) return nil } @@ -294,15 +417,6 @@ func GetStorageData() map[string]float64 { } } -// func RunSpaceMonitoring() { -// for { -// to_put, _ := json.Marshal(GetStorageData()) -// vars.StateDB.Put([]byte("Storage data"), to_put, nil) - -// time.Sleep(time.Second * 30) -// } -// } - var units = []struct { Suffix string Multiplier int64 diff --git a/application/backend/app/util/util_test.go b/application/backend/app/util/util_test.go index 0c1ec20..5a3c17a 100644 --- a/application/backend/app/util/util_test.go +++ b/application/backend/app/util/util_test.go @@ -9,30 +9,21 @@ import ( "github.com/devforth/OnLogs/app/vars" ) -func TestContains(t *testing.T) { - type args struct { - a string - list []string - } - tests := []struct { - name string - args args - want bool - }{ - {"Is contain 'a'", args{a: "a", list: []string{"a", "b", "c"}}, true}, - {"Is contain 'A'", args{a: "A", list: []string{"a", "b", "c"}}, false}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := Contains(tt.args.a, tt.args.list); got != tt.want { - t.Errorf("Contains() = %v, want %v", got, tt.want) - } - }) - } +// A token is only accepted while its account exists, so these fixtures need to. +func TestMain(m *testing.M) { + vars.UsersDB.Put([]byte("test_user"), []byte("irrelevant"), nil) + os.Exit(m.Run()) } func TestCreateInitUser(t *testing.T) { - CreateInitUser() + os.Setenv("ADMIN_USERNAME", "admin") + os.Setenv("ADMIN_PASSWORD", "an-actual-admin-password") + t.Cleanup(func() { os.Setenv("ADMIN_PASSWORD", "") }) + + if err := CreateInitUser(); err != nil { + t.Fatalf("CreateInitUser: %v", err) + } + isExist, err := vars.UsersDB.Has([]byte("admin"), nil) if err != nil { t.Error(err.Error()) @@ -42,27 +33,6 @@ func TestCreateInitUser(t *testing.T) { } } -func TestCreateJWT(t *testing.T) { - os.Setenv("JWT_SECRET", "1231efdZF") - token := CreateJWT("test_user") - - test_req, _ := http.NewRequest("GET", "", nil) - test_req.AddCookie( - &http.Cookie{ - Name: "onlogs-cookie", - Value: token, - }, - ) - - username, err := GetUserFromJWT(*test_req) - if err != nil { - t.Error(err) - } - if username != "test_user" { - t.Error("Username in JWT is wrong: ", username) - } -} - func TestGetHost(t *testing.T) { host, _ := os.Hostname() if host[len(host)-1] < 32 || host[len(host)-1] > 126 { diff --git a/application/backend/app/vars/connections.go b/application/backend/app/vars/connections.go new file mode 100644 index 0000000..72f664a --- /dev/null +++ b/application/backend/app/vars/connections.go @@ -0,0 +1,90 @@ +package vars + +import ( + "sync" + "time" + + "github.com/gorilla/websocket" +) + +const wsWriteDeadline = 10 * time.Second + +// gorilla permits at most one concurrent writer per connection and panics +// otherwise, so each viewer carries its own write lock. +type viewer struct { + conn *websocket.Conn + writeMu sync.Mutex +} + +func (v *viewer) write(messageType int, payload []byte) error { + v.writeMu.Lock() + defer v.writeMu.Unlock() + + v.conn.SetWriteDeadline(time.Now().Add(wsWriteDeadline)) + return v.conn.WriteMessage(messageType, payload) +} + +// AddConnection registers a viewer's websocket for a host/container. +func AddConnection(key string, conn *websocket.Conn) { + if conn == nil { + return + } + connectionsMutex.Lock() + defer connectionsMutex.Unlock() + connections[key] = append(connections[key], &viewer{conn: conn}) +} + +func viewersFor(key string) []*viewer { + connectionsMutex.RLock() + defer connectionsMutex.RUnlock() + return append([]*viewer{}, connections[key]...) +} + +func removeViewer(key string, target *viewer) { + connectionsMutex.Lock() + defer connectionsMutex.Unlock() + + remaining := connections[key][:0] + for _, existing := range connections[key] { + if existing != target { + remaining = append(remaining, existing) + } + } + if len(remaining) == 0 { + delete(connections, key) + return + } + connections[key] = remaining +} + +// Broadcast writes to every viewer of a host/container, dropping any connection +// that errors or stalls. A viewer that never drains its socket would otherwise +// block the caller forever, which freezes ingestion for that container. +func Broadcast(key string, messageType int, payload []byte) { + for _, v := range viewersFor(key) { + if err := v.write(messageType, payload); err != nil { + removeViewer(key, v) + v.conn.Close() + } + } +} + +func ConnectionCount(key string) int { + connectionsMutex.RLock() + defer connectionsMutex.RUnlock() + return len(connections[key]) +} + +// Total only. Per-key counts are not exported for metrics because the key is a +// bare container name locally and host/container for agent-forwarded streams, +// so the two forms would not label consistently. +func TotalConnections() int { + connectionsMutex.RLock() + defer connectionsMutex.RUnlock() + + total := 0 + for _, viewers := range connections { + total += len(viewers) + } + return total +} diff --git a/application/backend/app/vars/connections_test.go b/application/backend/app/vars/connections_test.go new file mode 100644 index 0000000..d3e815f --- /dev/null +++ b/application/backend/app/vars/connections_test.go @@ -0,0 +1,108 @@ +package vars + +import ( + "net/http" + "net/http/httptest" + "sync" + "testing" + "time" + + "github.com/gorilla/websocket" +) + +func dialTestSocket(t *testing.T) (*websocket.Conn, func()) { + t.Helper() + upgrader := websocket.Upgrader{CheckOrigin: func(*http.Request) bool { return true }} + + served := make(chan *websocket.Conn, 1) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + conn, err := upgrader.Upgrade(w, r, nil) + if err != nil { + return + } + served <- conn + })) + + url := "ws" + server.URL[len("http"):] + client, _, err := websocket.DefaultDialer.Dial(url, nil) + if err != nil { + server.Close() + t.Fatalf("dial: %v", err) + } + + serverConn := <-served + return serverConn, func() { + client.Close() + serverConn.Close() + server.Close() + } +} + +func TestConnectionsSurviveConcurrentRegistrationAndBroadcast(t *testing.T) { + key := "racehost/racecontainer" + conn, cleanup := dialTestSocket(t) + defer cleanup() + + var wg sync.WaitGroup + stop := make(chan struct{}) + + // The websocket-upgrade handler registering viewers. + wg.Add(1) + go func() { + defer wg.Done() + for { + select { + case <-stop: + return + default: + } + AddConnection(key+"-other", conn) + } + }() + + // The daemon goroutine fanning log lines out to viewers. + wg.Add(1) + go func() { + defer wg.Done() + for { + select { + case <-stop: + return + default: + } + Broadcast(key, websocket.TextMessage, []byte("line")) + } + }() + + time.Sleep(150 * time.Millisecond) + close(stop) + wg.Wait() +} + +func TestBroadcastDropsAConnectionThatFailsToWrite(t *testing.T) { + key := "deadhost/deadcontainer" + conn, cleanup := dialTestSocket(t) + defer cleanup() + + AddConnection(key, conn) + if ConnectionCount(key) != 1 { + t.Fatalf("expected the connection to be registered, got %d", ConnectionCount(key)) + } + + conn.Close() + Broadcast(key, websocket.TextMessage, []byte("line")) + + if got := ConnectionCount(key); got != 0 { + t.Fatalf("a dead connection was kept after a failed write: %d still registered", got) + } +} + +func TestAddConnectionIgnoresNil(t *testing.T) { + key := "nilhost/nilcontainer" + AddConnection(key, nil) + + if got := ConnectionCount(key); got != 0 { + t.Fatalf("a nil connection was stored; a background goroutine will dereference it (%d stored)", got) + } + Broadcast(key, websocket.TextMessage, []byte("line")) +} diff --git a/application/backend/app/vars/state.go b/application/backend/app/vars/state.go new file mode 100644 index 0000000..475d6d0 --- /dev/null +++ b/application/backend/app/vars/state.go @@ -0,0 +1,119 @@ +package vars + +import ( + "errors" + "sort" + "strings" + "sync" +) + +var stateMutex sync.RWMutex + +func ActiveStreams() []string { + stateMutex.RLock() + defer stateMutex.RUnlock() + return append([]string{}, Active_Daemon_Streams...) +} + +func AddActiveStream(container string) { + stateMutex.Lock() + defer stateMutex.Unlock() + for _, existing := range Active_Daemon_Streams { + if existing == container { + return + } + } + Active_Daemon_Streams = append(Active_Daemon_Streams, container) +} + +func RemoveActiveStream(container string) { + stateMutex.Lock() + defer stateMutex.Unlock() + + remaining := make([]string, 0, len(Active_Daemon_Streams)) + for _, existing := range Active_Daemon_Streams { + if existing != container { + remaining = append(remaining, existing) + } + } + Active_Daemon_Streams = remaining +} + +func DockerContainerList() []string { + stateMutex.RLock() + defer stateMutex.RUnlock() + return append([]string{}, DockerContainers...) +} + +func SetDockerContainers(containers []string) { + stateMutex.Lock() + defer stateMutex.Unlock() + DockerContainers = append([]string{}, containers...) +} + +func AddDockerContainer(container string) { + stateMutex.Lock() + defer stateMutex.Unlock() + for _, existing := range DockerContainers { + if existing == container { + return + } + } + DockerContainers = append(DockerContainers, container) +} + +func SetAgentContainers(host string, containers []string) { + stateMutex.Lock() + defer stateMutex.Unlock() + AgentsActiveContainers[host] = append([]string{}, containers...) +} + +func AgentContainers(host string) []string { + stateMutex.RLock() + defer stateMutex.RUnlock() + return append([]string{}, AgentsActiveContainers[host]...) +} + +// QueueDelete records a container whose docker logs a remote agent should clear. +func QueueDelete(host string, container string) { + stateMutex.Lock() + defer stateMutex.Unlock() + ToDelete[host] = append(ToDelete[host], container) +} + +// TakeQueuedDeletes returns and clears the queue for a host. +func TakeQueuedDeletes(host string) []string { + stateMutex.Lock() + defer stateMutex.Unlock() + + queued := ToDelete[host] + if len(queued) == 0 { + return []string{} + } + delete(ToDelete, host) + return queued +} + +// CheckDatabases reports the package-level LevelDB handles that failed to open. +// They are opened in variable initialisers, so without this the first +// dereference is a nil-pointer panic on whichever goroutine gets there first. +func CheckDatabases() error { + failures := []string{} + for name, err := range map[string]error{ + "leveldb/hostaliases": AliasDBErr, + "leveldb/favourites": FavsDBErr, + "leveldb/groups": GroupsDBErr, + "leveldb/users": UsersDBErr, + "leveldb/tokens": TokensDBErr, + "leveldb/usersSettings": SettingsDBErr, + } { + if err != nil { + failures = append(failures, name+": "+err.Error()) + } + } + if len(failures) == 0 { + return nil + } + sort.Strings(failures) + return errors.New("unable to open " + strings.Join(failures, "; ")) +} diff --git a/application/backend/app/vars/state_test.go b/application/backend/app/vars/state_test.go new file mode 100644 index 0000000..bc3c8ac --- /dev/null +++ b/application/backend/app/vars/state_test.go @@ -0,0 +1,62 @@ +package vars + +import ( + "sync" + "testing" + "time" +) + +func TestSharedStateSurvivesConcurrentAccess(t *testing.T) { + var wg sync.WaitGroup + stop := make(chan struct{}) + + writers := []func(){ + func() { AddActiveStream("container") }, + func() { RemoveActiveStream("container") }, + func() { AddDockerContainer("container") }, + func() { SetDockerContainers([]string{"a", "b"}) }, + func() { SetAgentContainers("host", []string{"a"}) }, + func() { QueueDelete("host", "container") }, + } + readers := []func(){ + func() { _ = ActiveStreams() }, + func() { _ = DockerContainerList() }, + func() { _ = AgentContainers("host") }, + func() { _ = TakeQueuedDeletes("host") }, + } + + for _, fn := range append(append([]func(){}, writers...), readers...) { + wg.Add(1) + go func(f func()) { + defer wg.Done() + for { + select { + case <-stop: + return + default: + } + f() + } + }(fn) + } + + time.Sleep(120 * time.Millisecond) + close(stop) + wg.Wait() +} + +func TestQueuedDeletesAreKeptPerHostAndDrainedOnce(t *testing.T) { + host := "queuehost" + _ = TakeQueuedDeletes(host) + + QueueDelete(host, "first") + QueueDelete(host, "second") + + queued := TakeQueuedDeletes(host) + if len(queued) != 2 || queued[0] != "first" || queued[1] != "second" { + t.Fatalf("queued deletions were dropped: %v", queued) + } + if again := TakeQueuedDeletes(host); len(again) != 0 { + t.Fatalf("the queue was not drained: %v", again) + } +} diff --git a/application/backend/app/vars/totalconnections_test.go b/application/backend/app/vars/totalconnections_test.go new file mode 100644 index 0000000..e5be8a9 --- /dev/null +++ b/application/backend/app/vars/totalconnections_test.go @@ -0,0 +1,33 @@ +package vars + +import "testing" + +func TestTotalConnections(t *testing.T) { + connectionsMutex.Lock() + connections = map[string][]*viewer{} + connectionsMutex.Unlock() + + if got := TotalConnections(); got != 0 { + t.Fatalf("empty: got %d, want 0", got) + } + + first, closeFirst := dialTestSocket(t) + defer closeFirst() + second, closeSecond := dialTestSocket(t) + defer closeSecond() + + AddConnection("container-a", first) + if got := TotalConnections(); got != 1 { + t.Errorf("one viewer: got %d, want 1", got) + } + + // Across keys, not within one. + AddConnection("host-b/container-b", second) + if got := TotalConnections(); got != 2 { + t.Errorf("two viewers on two keys: got %d, want 2", got) + } + + connectionsMutex.Lock() + connections = map[string][]*viewer{} + connectionsMutex.Unlock() +} diff --git a/application/backend/app/vars/vars.go b/application/backend/app/vars/vars.go index cfc8fb6..d84d198 100644 --- a/application/backend/app/vars/vars.go +++ b/application/backend/app/vars/vars.go @@ -1,18 +1,16 @@ package vars import ( - "strconv" "sync" + "sync/atomic" "time" - "github.com/gorilla/websocket" "github.com/syndtr/goleveldb/leveldb" ) var ( ActiveDBs = map[string]*leveldb.DB{} Stat_Containers_DBs = map[string]*leveldb.DB{} - Stat_Hosts_DBs = map[string]*leveldb.DB{} Statuses_DBs = map[string]*leveldb.DB{} BrokenLogs_DBs = map[string]*leveldb.DB{} ContainersMeta_DBs = map[string]*leveldb.DB{} @@ -23,22 +21,28 @@ var ( DockerContainers = []string{} AgentsActiveContainers = map[string][]string{} - ToDelete = map[string][]string{} - Connections = map[string][]*websocket.Conn{} + ToDelete = map[string][]string{} - Counters_For_Hosts_Last_30_Min = map[string]map[string]uint64{} - Container_Stat_Counter = map[string]map[string]uint64{} + // Reachable only through AddConnection/Broadcast/ConnectionCount so it + // cannot be touched without the lock. + connections = map[string][]*viewer{} - Mutex sync.Mutex - DBMutex sync.RWMutex + Container_Stat_Counter = map[string]map[string]uint64{} + Mutex sync.Mutex + DBMutex sync.RWMutex + connectionsMutex sync.RWMutex + + AliasDB, AliasDBErr = leveldb.OpenFile("leveldb/hostaliases", nil) FavsDB, FavsDBErr = leveldb.OpenFile("leveldb/favourites", nil) - StateDB, StateDBErr = leveldb.OpenFile("leveldb/state", nil) + GroupsDB, GroupsDBErr = leveldb.OpenFile("leveldb/groups", nil) UsersDB, UsersDBErr = leveldb.OpenFile("leveldb/users", nil) TokensDB, TokensDBErr = leveldb.OpenFile("leveldb/tokens", nil) SettingsDB, SettingsDBErr = leveldb.OpenFile("leveldb/usersSettings", nil) - Year = strconv.Itoa(time.Now().UTC().Year()) + // Here rather than in routes so app/metrics need not import the HTTP layer. + LoginFailures atomic.Uint64 + LoginBlocked atomic.Uint64 ) const ( diff --git a/application/backend/go.mod b/application/backend/go.mod index cecc671..9ccef16 100644 --- a/application/backend/go.mod +++ b/application/backend/go.mod @@ -1,13 +1,13 @@ module github.com/devforth/OnLogs -go 1.24.4 // switch to 1.25.x or at least 1.24.11 when possible +go 1.26.5 require ( - github.com/golang-jwt/jwt/v5 v5.3.0 + github.com/golang-jwt/jwt/v5 v5.3.1 github.com/gorilla/websocket v1.5.3 github.com/joho/godotenv v1.5.1 github.com/syndtr/goleveldb v1.0.0 - golang.org/x/sys v0.40.0 + golang.org/x/sys v0.47.0 ) require ( @@ -17,11 +17,12 @@ require ( github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/go-connections v0.6.0 // indirect + github.com/docker/go-connections v0.8.1 // indirect github.com/docker/go-units v0.5.0 // indirect - github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-logr/logr v1.4.3 // indirect + github.com/felixge/httpsnoop v1.1.0 // indirect + github.com/go-logr/logr v1.4.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/sys/atomicwriter v0.1.0 // indirect github.com/moby/term v0.5.2 // indirect @@ -30,21 +31,17 @@ require ( github.com/opencontainers/image-spec v1.1.1 // indirect github.com/pkg/errors v0.9.1 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect - go.opentelemetry.io/otel v1.39.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 // indirect - go.opentelemetry.io/otel/metric v1.39.0 // indirect - go.opentelemetry.io/otel/sdk v1.39.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.39.0 // indirect - go.opentelemetry.io/otel/trace v1.39.0 // indirect - golang.org/x/time v0.11.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.70.0 // indirect + go.opentelemetry.io/otel v1.45.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.45.0 // indirect + go.opentelemetry.io/otel/metric v1.45.0 // indirect + go.opentelemetry.io/otel/trace v1.45.0 // indirect + golang.org/x/time v0.15.0 // indirect gotest.tools/v3 v3.5.2 // indirect ) require ( github.com/docker/docker v28.5.2+incompatible github.com/golang/snappy v1.0.0 // indirect - golang.org/x/net v0.48.0 // indirect - golang.org/x/text v0.33.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/application/backend/go.sum b/application/backend/go.sum index e509341..4faf715 100644 --- a/application/backend/go.sum +++ b/application/backend/go.sum @@ -18,20 +18,20 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM= github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= -github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= +github.com/docker/go-connections v0.8.1 h1:JibmG5hULs5qXSr/cp/w3Pw5fZuStt4MOHMUExb29/M= +github.com/docker/go-connections v0.8.1/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeORc= +github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 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/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= -github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= +github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= @@ -42,8 +42,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0 h1:/Tnpcb2E0Pz/tN9s3bfEY2Q8ePCEX9iuS+cneUwncnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.30.0/go.mod h1:zOBXOsUaBSjKgmH4OGzV1esUpR3oUSCPYVd2cUBjKYY= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= @@ -79,44 +79,44 @@ github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFd github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= -go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= -go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0/go.mod h1:vnakAaFckOMiMtOIhFI2MNH4FYrZzXCYxmb1LlhoGz8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 h1:Ckwye2FpXkYgiHX7fyVrN1uA/UYd9ounqqTuSNAv0k4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0/go.mod h1:teIFJh5pW2y+AN7riv6IBPX2DuesS3HgP39mwOspKwU= -go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= -go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= -go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= -go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= -go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= -go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= -go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= -go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= -go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= -go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.70.0 h1:LMuyCAyfalSjDyjdC65nK6N0zoTT63+E/u95X0JovZI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.70.0/go.mod h1:085m8qbm4hgc8rZWGDEa4vmyyo2c3nPxUslYUKUIU04= +go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU= +go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.45.0 h1:QRefszxJmfPdjXUUm3j6iDzY03mTPXMjqErFqQ67vUg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.45.0/go.mod h1:Tiz03lTBVBrm7eWZBOidzEaYaJa8tjwGUGv6d8mlTyk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.45.0 h1:QBajQ2SrwQijzHyZbQlPsuIzpl/ll8DY6wPWsajeGcI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.45.0/go.mod h1:08ZQLjrPLQ6R4kAXvuOvODEer5Yh4CoFvll5qB2BCI8= +go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M= +go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s= +go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= +go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= +go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= +go.opentelemetry.io/otel/sdk/metric v1.45.0/go.mod h1:vUWUxDZvu1WVRj8JA8S0AdhsPrZoDpA2DdZauIh4mDA= +go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag= +go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc= +go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk= +go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= -golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE= +golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= +golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= -golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= -google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= -google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= +golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.83.0 h1:JeNZEKJFbQxArAMl+hiytHauacDNqJUllNfmIMmpqnQ= +google.golang.org/grpc v1.83.0/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= diff --git a/application/backend/main.go b/application/backend/main.go index add0599..904e0d9 100644 --- a/application/backend/main.go +++ b/application/backend/main.go @@ -2,32 +2,73 @@ package main import ( "context" + "crypto/rand" + "encoding/hex" "fmt" "net/http" "os" + "time" "github.com/devforth/OnLogs/app/daemon" "github.com/devforth/OnLogs/app/db" "github.com/devforth/OnLogs/app/docker" + "github.com/devforth/OnLogs/app/metrics" "github.com/devforth/OnLogs/app/routes" "github.com/devforth/OnLogs/app/streamer" "github.com/devforth/OnLogs/app/util" + "github.com/devforth/OnLogs/app/vars" "github.com/docker/docker/client" "github.com/joho/godotenv" ) +func ensureJWTSecret() error { + if os.Getenv("JWT_SECRET") != "" { + return nil + } + + if persisted, err := os.ReadFile("leveldb/JWT_secret"); err == nil && len(persisted) > 0 { + os.Setenv("JWT_SECRET", string(persisted)) + return nil + } + + buf := make([]byte, 32) + if _, err := rand.Read(buf); err != nil { + return fmt.Errorf("unable to generate a JWT secret: %w", err) + } + secret := hex.EncodeToString(buf) + + if err := os.MkdirAll("leveldb", 0700); err != nil { + return fmt.Errorf("unable to create leveldb directory for the JWT secret: %w", err) + } + if err := os.WriteFile("leveldb/JWT_secret", []byte(secret), 0600); err != nil { + return fmt.Errorf("unable to persist the generated JWT secret: %w", err) + } + + os.Setenv("JWT_SECRET", secret) + return nil +} + +// gorilla clears the connection deadlines after hijacking (server.go:251), so +// WriteTimeout does not reach the websocket at /api/v1/getLogsStream. +func newServer(port string, handler http.Handler) *http.Server { + return &http.Server{ + Addr: ":" + port, + Handler: handler, + ReadHeaderTimeout: 10 * time.Second, + ReadTimeout: 30 * time.Second, + WriteTimeout: 120 * time.Second, + IdleTimeout: 120 * time.Second, + } +} + func init_config() { if os.Getenv("PORT") == "" { os.Setenv("PORT", "2874") } - if os.Getenv("JWT_SECRET") == "" { - token, err := os.ReadFile("leveldb/JWT_secret") - if err != nil { - os.WriteFile("leveldb/JWT_secret", []byte(os.Getenv("JWT_SECRET")), 0700) - token, _ = os.ReadFile("leveldb/JWT_secret") - } - os.Setenv("JWT_SECRET", string(token)) + if err := ensureJWTSecret(); err != nil { + fmt.Println("FATAL:", err) + os.Exit(1) } if os.Getenv("DOCKER_HOST") == "" { @@ -37,6 +78,17 @@ func init_config() { if os.Getenv("MAX_LOGS_SIZE") == "" { os.Setenv("MAX_LOGS_SIZE", "10GB") } + if _, err := util.ParseHumanReadableSize(os.Getenv("MAX_LOGS_SIZE")); err != nil { + fmt.Printf("FATAL: MAX_LOGS_SIZE=%q is not a valid size (%v); log retention would never run.\n", + os.Getenv("MAX_LOGS_SIZE"), err) + os.Exit(1) + } + + if err := routes.SetTrustedProxies(os.Getenv("TRUSTED_PROXIES")); err != nil { + fmt.Printf("FATAL: TRUSTED_PROXIES=%q is invalid (%v); refusing to start with a rate limiter that cannot tell clients apart.\n", + os.Getenv("TRUSTED_PROXIES"), err) + os.Exit(1) + } fmt.Println("INFO: OnLogs configs done!") } @@ -45,6 +97,16 @@ func main() { godotenv.Load(".env") init_config() + if err := vars.CheckDatabases(); err != nil { + fmt.Println("FATAL:", err) + os.Exit(1) + } + + if os.Getenv("JWT_SECRET") == "" { + fmt.Println("FATAL: JWT_SECRET is empty; refusing to start. Unset it to have one generated, or set a non-empty value.") + os.Exit(1) + } + cli, err := client.NewClientWithOpts( client.FromEnv, client.WithAPIVersionNegotiation(), @@ -60,9 +122,7 @@ func main() { Client: cli, } - daemonService := &daemon.DaemonService{ - DockerClient: dockerService, - } + daemonService := daemon.NewDaemonService(dockerService) streamController := &streamer.StreamController{ DaemonService: daemonService, @@ -70,15 +130,22 @@ func main() { bgContext := context.Background() - if os.Getenv("AGENT") != "" { + if util.IsAgentMode() { streamController.StreamLogs(bgContext) } go db.DeleteUnusedTokens() + go metrics.StartSizeRefresher(bgContext) go streamController.StreamLogs(bgContext) - // go util.RunSpaceMonitoring() util.ReplacePrefixVariableForFrontend() - util.CreateInitUser() + if err := util.CreateInitUser(); err != nil { + if os.Getenv("DISABLE_AUTH") == "true" { + fmt.Println("WARNING:", err, "(DISABLE_AUTH=true, continuing without an administrator account)") + } else { + fmt.Println("FATAL:", err) + os.Exit(1) + } + } // Initialize the "Controller" with its dependencies routerCtrl := &routes.RouteController{ @@ -93,15 +160,18 @@ func main() { http.HandleFunc(pathPrefix+"/api/v1/askForDelete", routerCtrl.AskForDelete) http.HandleFunc(pathPrefix+"/api/v1/changeFavorite", routerCtrl.ChangeFavourite) http.HandleFunc(pathPrefix+"/api/v1/checkCookie", routerCtrl.CheckCookie) + http.HandleFunc(pathPrefix+"/api/v1/createGroup", routerCtrl.CreateGroup) http.HandleFunc(pathPrefix+"/api/v1/createUser", routerCtrl.CreateUser) http.HandleFunc(pathPrefix+"/api/v1/deleteContainer", routerCtrl.DeleteContainer) http.HandleFunc(pathPrefix+"/api/v1/deleteContainerLogs", routerCtrl.DeleteContainerLogs) http.HandleFunc(pathPrefix+"/api/v1/deleteDockerLogs", routerCtrl.DeleteDockerLogs) + http.HandleFunc(pathPrefix+"/api/v1/deleteGroup", routerCtrl.DeleteGroup) http.HandleFunc(pathPrefix+"/api/v1/deleteUser", routerCtrl.DeleteUser) - http.HandleFunc(pathPrefix+"/api/v1/editHostname", routerCtrl.EditHostname) http.HandleFunc(pathPrefix+"/api/v1/editUser", routerCtrl.EditUser) http.HandleFunc(pathPrefix+"/api/v1/getChartData", routerCtrl.GetChartData) http.HandleFunc(pathPrefix+"/api/v1/getDockerSize", routerCtrl.GetDockerSize) + http.HandleFunc(pathPrefix+"/api/v1/getGroups", routerCtrl.GetGroups) + http.HandleFunc(pathPrefix+"/api/v1/getHostAliases", routerCtrl.GetHostAliases) http.HandleFunc(pathPrefix+"/api/v1/getHosts", routerCtrl.GetHosts) http.HandleFunc(pathPrefix+"/api/v1/getLogWithPrev", routerCtrl.GetLogWithPrev) http.HandleFunc(pathPrefix+"/api/v1/getLogs", routerCtrl.GetLogs) @@ -116,8 +186,11 @@ func main() { http.HandleFunc(pathPrefix+"/api/v1/getUsers", routerCtrl.GetUsers) http.HandleFunc(pathPrefix+"/api/v1/login", routerCtrl.Login) http.HandleFunc(pathPrefix+"/api/v1/logout", routerCtrl.Logout) + http.HandleFunc(pathPrefix+"/api/v1/metrics", metrics.Handler(daemonService)) + http.HandleFunc(pathPrefix+"/api/v1/setHostAlias", routerCtrl.SetHostAlias) + http.HandleFunc(pathPrefix+"/api/v1/updateGroup", routerCtrl.UpdateGroup) http.HandleFunc(pathPrefix+"/api/v1/updateUserSettings", routerCtrl.UpdateUserSettings) fmt.Println("Listening on port:", string(os.Getenv("PORT"))+"...") - fmt.Println("ONLOGS: ", http.ListenAndServe(":"+string(os.Getenv("PORT")), nil)) + fmt.Println("ONLOGS: ", newServer(os.Getenv("PORT"), nil).ListenAndServe()) } diff --git a/application/backend/main_test.go b/application/backend/main_test.go new file mode 100644 index 0000000..3f8488a --- /dev/null +++ b/application/backend/main_test.go @@ -0,0 +1,94 @@ +package main + +import ( + "os" + "testing" + + "github.com/devforth/OnLogs/app/util" +) + +func TestInitConfigGeneratesAJWTSecretWhenNoneIsConfigured(t *testing.T) { + t.Chdir(t.TempDir()) + t.Setenv("JWT_SECRET", "") + + init_config() + + secret := os.Getenv("JWT_SECRET") + if len(secret) < 32 { + t.Fatalf("JWT secret is %d bytes, want at least 32: %q", len(secret), secret) + } + + persisted, err := os.ReadFile("leveldb/JWT_secret") + if err != nil { + t.Fatalf("secret was not persisted: %v", err) + } + if string(persisted) != secret { + t.Fatalf("persisted secret %q does not match the active one %q", persisted, secret) + } + + t.Setenv("JWT_SECRET", "") + init_config() + if os.Getenv("JWT_SECRET") != secret { + t.Fatalf("second boot changed the secret: %q -> %q", secret, os.Getenv("JWT_SECRET")) + } +} + +func TestInitConfigReplacesAnEmptySecretFile(t *testing.T) { + t.Chdir(t.TempDir()) + t.Setenv("JWT_SECRET", "") + + if err := os.MkdirAll("leveldb", 0o700); err != nil { + t.Fatal(err) + } + if err := os.WriteFile("leveldb/JWT_secret", nil, 0o600); err != nil { + t.Fatal(err) + } + + init_config() + + if len(os.Getenv("JWT_SECRET")) < 32 { + t.Fatalf("empty secret file was accepted, JWT_SECRET=%q", os.Getenv("JWT_SECRET")) + } +} + +func TestInitConfigKeepsAnExplicitlyConfiguredSecret(t *testing.T) { + t.Chdir(t.TempDir()) + t.Setenv("JWT_SECRET", "configured-by-the-operator") + + init_config() + + if os.Getenv("JWT_SECRET") != "configured-by-the-operator" { + t.Fatalf("configured secret was overwritten: %q", os.Getenv("JWT_SECRET")) + } + if _, err := os.Stat("leveldb/JWT_secret"); err == nil { + t.Fatal("a configured secret must not be written to disk") + } +} + +func TestNewServerSetsAllTimeouts(t *testing.T) { + s := newServer("2874", nil) + + if s.ReadHeaderTimeout == 0 { + t.Error("ReadHeaderTimeout is unset, so a slowloris client can hold a connection open forever") + } + if s.ReadTimeout == 0 { + t.Error("ReadTimeout is unset") + } + if s.WriteTimeout == 0 { + t.Error("WriteTimeout is unset") + } + if s.IdleTimeout == 0 { + t.Error("IdleTimeout is unset") + } +} + +func TestInitConfigRejectsAnUnparseableMaxLogsSize(t *testing.T) { + if _, err := util.ParseHumanReadableSize("10GB"); err != nil { + t.Fatalf("the default should parse: %v", err) + } + for _, value := range []string{"lots", "10 gigabytes", "GB", "-"} { + if _, err := util.ParseHumanReadableSize(value); err == nil { + t.Errorf("MAX_LOGS_SIZE=%q was accepted; retention would silently never run", value) + } + } +} diff --git a/application/build.sh b/application/build.sh deleted file mode 100755 index e66be8e..0000000 --- a/application/build.sh +++ /dev/null @@ -1,2 +0,0 @@ -# docker buildx create --use -docker buildx build --load --platform=linux/amd64,linux/arm64 --tag "devforth/onlogs:latest" --tag "devforth/onlogs:1.1.11" . diff --git a/application/compose-local-test.yml b/application/compose-local-test.yml index 06a6dfb..9b5f4de 100644 --- a/application/compose-local-test.yml +++ b/application/compose-local-test.yml @@ -33,6 +33,7 @@ services: - DOCKER_HOST=http://docker-socket-proxy:2375 - DOCKER_API_VERSION=1.46 - MAX_LOGS_SIZE=10GB + - METRICS_TOKEN=local-metrics-token volumes: - onlogs-leveldb:/leveldb - /etc/hostname:/etc/hostname:ro diff --git a/application/frontend/.storybook/main.cjs b/application/frontend/.storybook/main.cjs deleted file mode 100644 index c510332..0000000 --- a/application/frontend/.storybook/main.cjs +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = { - "stories": [ - "../src/**/*.stories.mdx", - "../src/**/*.stories.@(js|jsx|ts|tsx|svelte)" - ], - "addons": [ - "@storybook/addon-links", - "@storybook/addon-essentials", - "@storybook/addon-interactions" - ], - "framework": "@storybook/svelte", - "core": { - "builder": "@storybook/builder-vite" - }, - "features": { - "storyStoreV7": true - } -} \ No newline at end of file diff --git a/application/frontend/.storybook/preview-head.html b/application/frontend/.storybook/preview-head.html deleted file mode 100644 index 05da1e9..0000000 --- a/application/frontend/.storybook/preview-head.html +++ /dev/null @@ -1,3 +0,0 @@ - \ No newline at end of file diff --git a/application/frontend/.storybook/preview.cjs b/application/frontend/.storybook/preview.cjs deleted file mode 100644 index 180cf9a..0000000 --- a/application/frontend/.storybook/preview.cjs +++ /dev/null @@ -1,11 +0,0 @@ -import "../src/main.scss"; - -export const parameters = { - actions: { argTypesRegex: "^on[A-Z].*" }, - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/, - }, - }, -}; diff --git a/application/frontend/index.html b/application/frontend/index.html index a46b8a3..78a43c7 100644 --- a/application/frontend/index.html +++ b/application/frontend/index.html @@ -2,9 +2,6 @@ - - - =6.0.0" + "@sveltejs/vite-plugin-svelte": "^7.2.0", + "@vusion/webfonts-generator": "^0.8.0", + "esbuild": "^0.28.1", + "fs-extra": "^11.4.0", + "jsdom": "^30.0.1", + "sass": "^1.102.0", + "svelte": "^5.56.8", + "svelte-intersection-observer": "^2.2.0", + "vite": "^8.2.1" } }, "node_modules/@asamuzakjp/css-color": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", - "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-6.0.5.tgz", + "integrity": "sha512-mbhpPMmnw/kwW19aRNmSUl1QzLbdGo1SCuE49BT98MNwqF6zaHb3o2owssFc/PEO/4t2UjqtCNwocuDtJornzA==", "dev": true, "license": "MIT", "dependencies": { - "@csstools/css-calc": "^2.1.3", - "@csstools/css-color-parser": "^3.0.9", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "lru-cache": "^10.4.3" - } - }, - "node_modules/@asamuzakjp/css-color/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==", - "dev": true, - "license": "ISC" - }, - "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.3.tgz", - "integrity": "sha512-prBHMK4JYYK+wDjJF1q99KK4JLL+egWS4nmNqdlMUgCExMZ+iZW0hGhyC3VEbsPjvaN0TBhW//VIFwBrk8sEiw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", - "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.3", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-module-transforms": "^7.19.0", - "@babel/helpers": "^7.19.0", - "@babel/parser": "^7.19.3", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.3", - "@babel/types": "^7.19.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.3.tgz", - "integrity": "sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.19.3", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" + "@csstools/css-calc": "^3.2.1", + "@csstools/css-color-parser": "^4.1.9", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0", + "lru-cache": "^11.5.2" }, "engines": { - "node": ">=6.9.0" + "node": "^22.13.0 || >=24.0.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "node_modules/@asamuzakjp/dom-selector": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-8.3.2.tgz", + "integrity": "sha512-93Z1N+BQNXysodoicpOIyNh2drHfz/CTf9nnT0FEx72GJcIiwgydD7tGAr78j41LsYn3hlRn+LdGPuBLn1Bl8Q==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "bidi-js": "^1.0.3", + "css-tree": "^3.2.1", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.5.2" }, "engines": { - "node": ">=6.0.0" + "node": "^22.13.0 || >=24.0.0" } }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "node_modules/@bramus/specificity": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.18.6" + "css-tree": "^3.0.0" }, - "engines": { - "node": ">=6.9.0" + "bin": { + "specificity": "bin/cli.js" } }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "node_modules/@csstools/color-helpers": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.1.0.tgz", + "integrity": "sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==", "dev": true, - "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", "engines": { - "node": ">=6.9.0" + "node": ">=20.19.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz", - "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==", + "node_modules/@csstools/css-calc": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.3.0.tgz", + "integrity": "sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==", "dev": true, - "dependencies": { - "@babel/compat-data": "^7.19.3", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "semver": "^6.3.0" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=20.19.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" } }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", - "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", + "node_modules/@csstools/css-color-parser": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.10.tgz", + "integrity": "sha512-UZhQLIUyJaaMepqehrCODwCg2KW25vFvLWBmqYFaPclYvvxzj/sG8LBOhBFCp11i9uE7t1EyS+RAoV9tztPFyw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.9", - "@babel/helper-split-export-declaration": "^7.18.6" + "@csstools/color-helpers": "^6.1.0", + "@csstools/css-calc": "^3.3.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=20.19.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz", - "integrity": "sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==", + "node_modules/@csstools/css-parser-algorithms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.1.0" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=20.19.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@csstools/css-tokenizer": "^4.0.0" } }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", - "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.7.tgz", + "integrity": "sha512-fQ+05118eQS1cofO3aJpB5efgpBZMvIzwr/sbC8kDLVA5XLG8q1kJV5yzrUAI1f7lvhPnm8fgIjzFB8/O/5Dig==", "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", "peerDependencies": { - "@babel/core": "^7.4.0-0" + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "node_modules/@csstools/css-tokenizer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=20.19.0" } }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.9" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", - "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=18" } }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz", - "integrity": "sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/traverse": "^7.19.1", - "@babel/types": "^7.19.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", - "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz", - "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.18.9" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", - "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz", - "integrity": "sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], "dev": true, - "dependencies": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/helpers": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz", - "integrity": "sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==", + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@babel/parser": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.3.tgz", - "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=6.0.0" + "node": ">=18" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.18.6", - "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.18.6.tgz", - "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=18" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz", - "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", - "@babel/plugin-proposal-optional-chaining": "^7.18.9" - }, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" + "node": ">=18" } }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz", - "integrity": "sha512-0yu8vNATgLy4ivqMNBIwb1HebCelqN7YX8SL3FDXORv/RqT0zEEWUCH4GH44JsSrvCu6GqnAdR5EBFAPeNBB4Q==", + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", - "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" + "node": ">=18" } }, - "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.19.3.tgz", - "integrity": "sha512-MbgXtNXqo7RTKYIXVchVJGPvaVufQH3pxvQyfbGvNw1DObIhph+PesYXJTcd8J4DdWibvf6Z2eanOyItX8WnJg==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.19.0", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-replace-supers": "^7.19.1", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/plugin-syntax-decorators": "^7.19.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18" } }, - "node_modules/@babel/plugin-proposal-export-default-from": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.18.10.tgz", - "integrity": "sha512-5H2N3R2aQFxkV4PIBUR/i7PUSwgTZjouJKzI8eKswfIjT0PhvzkPn0t0wIS5zn6maQuvtT0t1oHtMUz61LOuow==", + "node_modules/@exodus/bytes": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz", + "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-default-from": "^7.18.6" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } } }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "dev": true, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz", - "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, + "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==", + "license": "MIT", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "dev": true, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "node_modules/@kurkle/color": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", + "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", + "license": "MIT" + }, + "node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", "dev": true, + "license": "ISC", "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz", - "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==", + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.18.8", - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.18.8" + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "node_modules/@oxc-project/types": { + "version": "0.143.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.143.0.tgz", + "integrity": "sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" } }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz", - "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==", + "node_modules/@parcel/watcher": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.6.0.tgz", + "integrity": "sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==", "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.4" }, "engines": { - "node": ">=6.9.0" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.6.0", + "@parcel/watcher-darwin-arm64": "2.6.0", + "@parcel/watcher-darwin-x64": "2.6.0", + "@parcel/watcher-freebsd-x64": "2.6.0", + "@parcel/watcher-linux-arm-glibc": "2.6.0", + "@parcel/watcher-linux-arm-musl": "2.6.0", + "@parcel/watcher-linux-arm64-glibc": "2.6.0", + "@parcel/watcher-linux-arm64-musl": "2.6.0", + "@parcel/watcher-linux-x64-glibc": "2.6.0", + "@parcel/watcher-linux-x64-musl": "2.6.0", + "@parcel/watcher-win32-arm64": "2.6.0", + "@parcel/watcher-win32-x64": "2.6.0" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.6.0.tgz", + "integrity": "sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", - "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.6.0.tgz", + "integrity": "sha512-Y3QV0gl7Q1zbfueunkWIERICbEojQFCgpyG7YqOGNFLsckXyI1xu9mAIUpKY9QBYzBtSkN8dBPwd3yiAO9ovMw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.6.0.tgz", + "integrity": "sha512-Ohv6OpzhUfKYD7Beb8kDvG0jbIxORCYY1JRdZnaBtnjjkJxgD7ZVL0nw2sCYd0yTMKTvz3nnTnOF3cDifK+kvw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=4" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "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==", + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.6.0.tgz", + "integrity": "sha512-5HmXvDgs8VK+74jF9y9/2FE3/OnlcKmc56tjmSrEuZjpSZOGL+fvAu+HKJBdPs9uwoP2hE6TlSUpXZ/C5jUFmQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "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==", + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.6.0.tgz", + "integrity": "sha512-Ps/hui3A+vMbjdqlqAowK2ZL8+BO8dBjxeWXj6npTBs3jx4wWmbPpaLuqwrQrSqIVMCnpWo238bJ1U37GhQOYg==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "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==", + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.6.0.tgz", + "integrity": "sha512-9c6AUHgHoG+IY88MRIHupztQiQnrbqHYQjkM2btA+Bf/wQnQMuiD0Wfk1EVv3TlNT3x41uU71rn6E4xh/+zvkw==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.19.0.tgz", - "integrity": "sha512-xaBZUEDntt4faL1yN8oIFlhfXeQAWJW7CLKYsHTUqriCUbj8xOra8bfxxKGi/UwExPFBuPdH4XfHc9rGQhrVkQ==", + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.6.0.tgz", + "integrity": "sha512-yHRqS2owEXe6Hic9z6Mh1ECsCd+ODVOGvZDyciqRd21+v+o+DnXMOrw50DSpIG2sb8GPEaPPmfeCAWKPJdq46g==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "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==", + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.6.0.tgz", + "integrity": "sha512-WhB2e/V7rqdHHWZusBSPuy5Ei8S6lSz6FE5TKKQz5h3a0O+C+mhY7vxU9b/stqvMb8beLnPY82ZrFTLKs+SrKA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@babel/plugin-syntax-export-default-from": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.18.6.tgz", - "integrity": "sha512-Kr//z3ujSVNx6E9z9ih5xXXMqK07VVTuqPmqGe6Mss/zW5XPeLZeSDZoP9ab/hT4wPKqAgjl2PnhPrcpk8Seew==", + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.6.0.tgz", + "integrity": "sha512-ulGE6x6Oz6iAwg75T8YQSoguBWasniIbX+QWpaYPcCnDOpdWX3k+4xbEYPZVLxOuoJI+svJJPD3sEj8G7lrQ3A==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "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==", + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.6.0.tgz", + "integrity": "sha512-tkBYKt7YQrjIJWYDnto2YgO8MRkjlMTSNoRHzsXinBqbLdeOM3L32wPZJvIZxqaLMfSlS/4sUjH/6STVP/XDLw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", - "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.6.0.tgz", + "integrity": "sha512-gIZAP23jaHjGWasY/TY6yL7NHFClf0Ga7FN+iINvk+KN94rhm94lYZhFsbYFNcA04/onvGD9kKmiJLJB2HbNwQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "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==", + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.6.0.tgz", + "integrity": "sha512-cA+/pXV2YkfxlIcXOQ5fSWqAzzPyD78/x5qbK/I0vUkrlYHA8TIz+MXjAbGouguKVSI4bOmkTSJ1/poVSsgt+A==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz", + "integrity": "sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^20.19.0 || >=22.12.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==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.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==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.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==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz", + "integrity": "sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.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==", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz", + "integrity": "sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.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==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz", + "integrity": "sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.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==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz", + "integrity": "sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.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==", + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz", + "integrity": "sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^20.19.0 || >=22.12.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==", + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz", + "integrity": "sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==", + "cpu": [ + "s390x" + ], "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", - "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", - "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", - "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-remap-async-to-generator": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", - "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz", - "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz", - "integrity": "sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.19.0", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-replace-supers": "^7.18.9", - "@babel/helper-split-export-declaration": "^7.18.6", - "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.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz", - "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.18.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz", - "integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", - "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", - "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-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", - "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", - "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", - "dev": true, - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", - "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", - "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", - "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", - "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", - "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", - "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz", - "integrity": "sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A==", - "dev": true, - "dependencies": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.19.0", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-validator-identifier": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", - "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz", - "integrity": "sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.19.0", - "@babel/helper-plugin-utils": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", - "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", - "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", - "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", - "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", - "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz", - "integrity": "sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/plugin-syntax-jsx": "^7.18.6", - "@babel/types": "^7.19.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", - "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", - "dev": true, - "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.18.6.tgz", - "integrity": "sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.18.6.tgz", - "integrity": "sha512-utZmlASneDfdaMh0m/WausbjUjEdGrQJz0vFK93d7wD3xf5wBtX219+q6IlCNZeguIcxS2f/CvLZrlLSvSHQXw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", - "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", - "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "regenerator-transform": "^0.15.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", - "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", - "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz", - "integrity": "sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", - "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", - "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", - "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.19.3.tgz", - "integrity": "sha512-z6fnuK9ve9u/0X0rRvI9MY0xg+DOUaABDYOe+/SQTxtlptaBB/V9JIUxJn6xp3lMBeb9qe8xSFmHU35oZDXD+w==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.19.0", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/plugin-syntax-typescript": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", - "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", - "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", - "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-0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.19.3.tgz", - "integrity": "sha512-ziye1OTc9dGFOAXSWKUqQblYHNlBOaDl8wzqf2iKXJAltYiR3hKHUKmkt+S9PppW7RQpq4fFCrwwpIDj/f5P4w==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.19.3", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-async-generator-functions": "^7.19.1", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.18.9", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@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.18.6", - "@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-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.18.9", - "@babel/plugin-transform-classes": "^7.19.0", - "@babel/plugin-transform-computed-properties": "^7.18.9", - "@babel/plugin-transform-destructuring": "^7.18.13", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.9", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.8", - "@babel/plugin-transform-function-name": "^7.18.9", - "@babel/plugin-transform-literals": "^7.18.9", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.18.6", - "@babel/plugin-transform-modules-commonjs": "^7.18.6", - "@babel/plugin-transform-modules-systemjs": "^7.19.0", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.18.8", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.19.0", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.9", - "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.19.3", - "babel-plugin-polyfill-corejs2": "^0.3.3", - "babel-plugin-polyfill-corejs3": "^0.6.0", - "babel-plugin-polyfill-regenerator": "^0.4.1", - "core-js-compat": "^3.25.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-react": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz", - "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-transform-react-display-name": "^7.18.6", - "@babel/plugin-transform-react-jsx": "^7.18.6", - "@babel/plugin-transform-react-jsx-development": "^7.18.6", - "@babel/plugin-transform-react-pure-annotations": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-typescript": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", - "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-transform-typescript": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/register": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.18.9.tgz", - "integrity": "sha512-ZlbnXDcNYHMR25ITwwNKT88JiaukkdVj/nG7r3wnuXkOTHc60Uy05PwMCPre0hSkY68E6zK3xz+vUJSP2jWmcw==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "find-cache-dir": "^2.0.0", - "make-dir": "^2.1.0", - "pirates": "^4.0.5", - "source-map-support": "^0.5.16" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz", - "integrity": "sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.2" - } - }, - "node_modules/@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.3.tgz", - "integrity": "sha512-qh5yf6149zhq2sgIXmwjnsvmnNQC2iw70UFjp4olxucKrWd/dvlUsBI88VSLUsnMNF7/vnOiA+nk1+yLoCqROQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.3", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.3", - "@babel/types": "^7.19.3", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.3.tgz", - "integrity": "sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.18.10", - "@babel/helper-validator-identifier": "^7.19.1", - "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/@cnakazawa/watch": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", - "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", - "dev": true, - "dependencies": { - "exec-sh": "^0.3.2", - "minimist": "^1.2.0" - }, - "bin": { - "watch": "cli.js" - }, - "engines": { - "node": ">=0.1.95" - } - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@csstools/color-helpers": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", - "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" - } - }, - "node_modules/@csstools/css-calc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", - "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" - } - }, - "node_modules/@csstools/css-color-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", - "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "dependencies": { - "@csstools/color-helpers": "^5.1.0", - "@csstools/css-calc": "^2.1.4" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" - } - }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", - "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.4" - } - }, - "node_modules/@csstools/css-tokenizer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", - "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@design-systems/utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@design-systems/utils/-/utils-2.12.0.tgz", - "integrity": "sha512-Y/d2Zzr+JJfN6u1gbuBUb1ufBuLMJJRZQk+dRmw8GaTpqKx5uf7cGUYGTwN02dIb3I+Tf+cW8jcGBTRiFxdYFg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.11.2", - "clsx": "^1.0.4", - "focus-lock": "^0.8.0", - "react-merge-refs": "^1.0.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": ">= 16.8.6", - "react-dom": ">= 16.8.6" - } - }, - "node_modules/@design-systems/utils/node_modules/@babel/runtime": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz", - "integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@devtools-ds/object-inspector": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@devtools-ds/object-inspector/-/object-inspector-1.2.0.tgz", - "integrity": "sha512-VztcwqVwScSvYdvJVZBJYsVO/2Pew3JPpFV3T9fuCHQLlHcLYOV3aU/kBS2ScuE2O1JN0ZbobLqFLa3vQF54Fw==", - "dev": true, - "dependencies": { - "@babel/runtime": "7.7.2", - "@devtools-ds/object-parser": "^1.2.0", - "@devtools-ds/themes": "^1.2.0", - "@devtools-ds/tree": "^1.2.0", - "clsx": "1.1.0" - }, - "peerDependencies": { - "react": ">= 16.8.6" - } - }, - "node_modules/@devtools-ds/object-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@devtools-ds/object-parser/-/object-parser-1.2.0.tgz", - "integrity": "sha512-SjGGyiFFY8dtUpiWXAvRSzRT+hE11EAAysrq2PsC/GVLf2ZLyT2nHlQO5kDStywyTz+fjw7S7pyDRj1HG9YTTA==", - "dev": true, - "dependencies": { - "@babel/runtime": "~7.5.4" - } - }, - "node_modules/@devtools-ds/object-parser/node_modules/@babel/runtime": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz", - "integrity": "sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.2" - } - }, - "node_modules/@devtools-ds/themes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@devtools-ds/themes/-/themes-1.2.0.tgz", - "integrity": "sha512-LimEITorE6yWZWWuMc6OiBfLQgPrQqWbyMEmfRUDPa3PHXoAY4SpDxczfg31fgyRDUNWnZhjaJH5bBbu8VEbIw==", - "dev": true, - "dependencies": { - "@babel/runtime": "~7.5.4", - "@design-systems/utils": "2.12.0", - "clsx": "1.1.0" - }, - "peerDependencies": { - "react": ">= 16.8.6" - } - }, - "node_modules/@devtools-ds/themes/node_modules/@babel/runtime": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz", - "integrity": "sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.2" - } - }, - "node_modules/@devtools-ds/tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@devtools-ds/tree/-/tree-1.2.0.tgz", - "integrity": "sha512-hC4g4ocuo2eg7jsnzKdauxH0sDQiPW3KSM2+uK3kRgcmr9PzpBD5Kob+Y/WFSVKswFleftOGKL4BQLuRv0sPxA==", - "dev": true, - "dependencies": { - "@babel/runtime": "7.7.2", - "@devtools-ds/themes": "^1.2.0", - "clsx": "1.1.0" - }, - "peerDependencies": { - "react": ">= 16.8.6" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.2.tgz", - "integrity": "sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.15.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/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/@eslint/eslintrc/node_modules/espree": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", - "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", - "dev": true, - "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "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/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/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/transform": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz", - "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.1.0", - "@jest/types": "^26.6.2", - "babel-plugin-istanbul": "^6.0.0", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.6.2", - "jest-regex-util": "^26.0.0", - "jest-util": "^26.6.2", - "micromatch": "^4.0.2", - "pirates": "^4.0.1", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/@jest/transform/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/transform/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/@jest/transform/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/transform/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/transform/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/@jest/transform/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/@jest/types": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", - "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/types/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/@jest/types/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/types/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/types/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/@jest/types/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/@joshwooding/vite-plugin-react-docgen-typescript": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@joshwooding/vite-plugin-react-docgen-typescript/-/vite-plugin-react-docgen-typescript-0.0.5.tgz", - "integrity": "sha512-HwAEj/vAP1+hzBfIv9DTCyg+1O0/LG48Up7j1RmJ+pFwjb/wRxzUBco4LqKFKe7SZ0M6IyASNh1oKP3yHnJElA==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^4.2.1", - "glob": "^7.2.0", - "glob-promise": "^4.2.0", - "magic-string": "^0.26.1", - "react-docgen-typescript": "^2.1.1" - }, - "peerDependencies": { - "typescript": ">= 4.3.x", - "vite": ">2.0.0-0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", - "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@kurkle/color": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", - "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" - }, - "node_modules/@mdx-js/mdx": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", - "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", - "dev": true, - "dependencies": { - "@babel/core": "7.12.9", - "@babel/plugin-syntax-jsx": "7.12.1", - "@babel/plugin-syntax-object-rest-spread": "7.8.3", - "@mdx-js/util": "1.6.22", - "babel-plugin-apply-mdx-type-prop": "1.6.22", - "babel-plugin-extract-import-names": "1.6.22", - "camelcase-css": "2.0.1", - "detab": "2.0.4", - "hast-util-raw": "6.0.1", - "lodash.uniq": "4.5.0", - "mdast-util-to-hast": "10.0.1", - "remark-footnotes": "2.0.0", - "remark-mdx": "1.6.22", - "remark-parse": "8.0.3", - "remark-squeeze-paragraphs": "4.0.0", - "style-to-object": "0.3.0", - "unified": "9.2.0", - "unist-builder": "2.0.3", - "unist-util-visit": "2.0.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@mdx-js/mdx/node_modules/@babel/core": { - "version": "7.12.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", - "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.5", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.5", - "@babel/parser": "^7.12.7", - "@babel/template": "^7.12.7", - "@babel/traverse": "^7.12.9", - "@babel/types": "^7.12.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@mdx-js/mdx/node_modules/@babel/plugin-syntax-jsx": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", - "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@mdx-js/mdx/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@mdx-js/mdx/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@mdx-js/react": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", - "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "react": "^16.13.1 || ^17.0.0" - } - }, - "node_modules/@mdx-js/util": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", - "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "dev": true, - "dependencies": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@mrmlnc/readdir-enhanced/node_modules/glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==", - "dev": true - }, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "dev": true, - "dependencies": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", - "dev": true, - "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/@storybook/addon-actions": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.5.13.tgz", - "integrity": "sha512-3Tji0gIy95havhTpSc6CsFl5lNxGn4O5Y1U9fyji+GRkKqDFOrvVLYAHPtLOpYdEI5tF0bDo+akiqfDouY8+eA==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/api": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/components": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "polished": "^4.2.2", - "prop-types": "^15.7.2", - "react-inspector": "^5.1.0", - "regenerator-runtime": "^0.13.7", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2", - "uuid-browser": "^3.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-actions/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-actions/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-actions/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-actions/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-actions/node_modules/@storybook/components": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.13.tgz", - "integrity": "sha512-6Hhx70JK5pGfKCkqMU4yq/BBH+vRTmzj7tZKfPwba+f8VmTMoOr/2ysTQFRtXryiHB6Z15xBYgfq5x2pIwQzLQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-actions/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-actions/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-actions/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-backgrounds": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-6.5.13.tgz", - "integrity": "sha512-b4JX7JMY7e50y1l6g71D+2XWV3GO0TO2z1ta8J6W4OQt8f44V7sSkRQaJUzXdLjQMrA+Anojuy1ZwPjVeLC6vg==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/api": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/components": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "global": "^4.4.0", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-backgrounds/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-backgrounds/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-backgrounds/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-backgrounds/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-backgrounds/node_modules/@storybook/components": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.13.tgz", - "integrity": "sha512-6Hhx70JK5pGfKCkqMU4yq/BBH+vRTmzj7tZKfPwba+f8VmTMoOr/2ysTQFRtXryiHB6Z15xBYgfq5x2pIwQzLQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-backgrounds/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-backgrounds/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-backgrounds/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-controls": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-6.5.13.tgz", - "integrity": "sha512-lYq3uf2mlVevm0bi6ueL3H6TpUMRYW9s/pTNTVJT225l27kLdFR9wEKxAkCBrlKaTgDLJmzzDRsJE3NLZlR/5Q==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/api": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/components": "6.5.13", - "@storybook/core-common": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/node-logger": "6.5.13", - "@storybook/store": "6.5.13", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "lodash": "^4.17.21", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-controls/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", - "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@storybook/addon-controls/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-controls/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-controls/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-controls/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-controls/node_modules/@storybook/components": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.13.tgz", - "integrity": "sha512-6Hhx70JK5pGfKCkqMU4yq/BBH+vRTmzj7tZKfPwba+f8VmTMoOr/2ysTQFRtXryiHB6Z15xBYgfq5x2pIwQzLQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-controls/node_modules/@storybook/core-common": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.5.13.tgz", - "integrity": "sha512-+DVZrRsteE9pw0X5MNffkdBgejQnbnL+UOG3qXkE9xxUamQALnuqS/w1BzpHE9WmOHuf7RWMKflyQEW3OLKAJg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.10", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-decorators": "^7.12.12", - "@babel/plugin-proposal-export-default-from": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.7", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-proposal-private-property-in-object": "^7.12.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.12", - "@babel/plugin-transform-classes": "^7.12.1", - "@babel/plugin-transform-destructuring": "^7.12.1", - "@babel/plugin-transform-for-of": "^7.12.1", - "@babel/plugin-transform-parameters": "^7.12.1", - "@babel/plugin-transform-shorthand-properties": "^7.12.1", - "@babel/plugin-transform-spread": "^7.12.1", - "@babel/preset-env": "^7.12.11", - "@babel/preset-react": "^7.12.10", - "@babel/preset-typescript": "^7.12.7", - "@babel/register": "^7.12.1", - "@storybook/node-logger": "6.5.13", - "@storybook/semver": "^7.3.2", - "@types/node": "^14.0.10 || ^16.0.0", - "@types/pretty-hrtime": "^1.0.0", - "babel-loader": "^8.0.0", - "babel-plugin-macros": "^3.0.1", - "babel-plugin-polyfill-corejs3": "^0.1.0", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "express": "^4.17.1", - "file-system-cache": "^1.0.5", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.0.4", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "handlebars": "^4.7.7", - "interpret": "^2.2.0", - "json5": "^2.1.3", - "lazy-universal-dotenv": "^3.0.1", - "picomatch": "^2.3.0", - "pkg-dir": "^5.0.0", - "pretty-hrtime": "^1.0.3", - "resolve-from": "^5.0.0", - "slash": "^3.0.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2", - "webpack": "4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-controls/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-controls/node_modules/@storybook/node-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.13.tgz", - "integrity": "sha512-/r5aVZAqZRoy5FyNk/G4pj7yKJd3lJfPbAaOHVROv2IF7PJP/vtRaDkcfh0g2U6zwuDxGIqSn80j+qoEli9m5A==", - "dev": true, - "dependencies": { - "@types/npmlog": "^4.1.2", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "npmlog": "^5.0.1", - "pretty-hrtime": "^1.0.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-controls/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-controls/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-controls/node_modules/@types/node": { - "version": "16.18.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", - "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", - "dev": true - }, - "node_modules/@storybook/addon-controls/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@storybook/addon-controls/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", - "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.1.5", - "core-js-compat": "^3.8.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@storybook/addon-controls/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/@storybook/addon-controls/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@storybook/addon-controls/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@storybook/addon-controls/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/@storybook/addon-controls/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/@storybook/addon-controls/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/@storybook/addon-docs": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-6.5.13.tgz", - "integrity": "sha512-RG/NjsheD9FixZ789RJlNyNccaR2Cuy7CtAwph4oUNi3aDFjtOI8Oe9L+FOT7qtVnZLw/YMjF+pZxoDqJNKLPw==", - "dev": true, - "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.12.12", - "@babel/preset-env": "^7.12.11", - "@jest/transform": "^26.6.2", - "@mdx-js/react": "^1.6.22", - "@storybook/addons": "6.5.13", - "@storybook/api": "6.5.13", - "@storybook/components": "6.5.13", - "@storybook/core-common": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/docs-tools": "6.5.13", - "@storybook/mdx1-csf": "^0.0.1", - "@storybook/node-logger": "6.5.13", - "@storybook/postinstall": "6.5.13", - "@storybook/preview-web": "6.5.13", - "@storybook/source-loader": "6.5.13", - "@storybook/store": "6.5.13", - "@storybook/theming": "6.5.13", - "babel-loader": "^8.0.0", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "regenerator-runtime": "^0.13.7", - "remark-external-links": "^8.0.0", - "remark-slug": "^6.0.0", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "@storybook/mdx2-csf": "^0.0.3", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@storybook/mdx2-csf": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-docs/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", - "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@storybook/addon-docs/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-docs/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-docs/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-docs/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-docs/node_modules/@storybook/components": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.13.tgz", - "integrity": "sha512-6Hhx70JK5pGfKCkqMU4yq/BBH+vRTmzj7tZKfPwba+f8VmTMoOr/2ysTQFRtXryiHB6Z15xBYgfq5x2pIwQzLQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-docs/node_modules/@storybook/core-common": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.5.13.tgz", - "integrity": "sha512-+DVZrRsteE9pw0X5MNffkdBgejQnbnL+UOG3qXkE9xxUamQALnuqS/w1BzpHE9WmOHuf7RWMKflyQEW3OLKAJg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.10", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-decorators": "^7.12.12", - "@babel/plugin-proposal-export-default-from": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.7", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-proposal-private-property-in-object": "^7.12.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.12", - "@babel/plugin-transform-classes": "^7.12.1", - "@babel/plugin-transform-destructuring": "^7.12.1", - "@babel/plugin-transform-for-of": "^7.12.1", - "@babel/plugin-transform-parameters": "^7.12.1", - "@babel/plugin-transform-shorthand-properties": "^7.12.1", - "@babel/plugin-transform-spread": "^7.12.1", - "@babel/preset-env": "^7.12.11", - "@babel/preset-react": "^7.12.10", - "@babel/preset-typescript": "^7.12.7", - "@babel/register": "^7.12.1", - "@storybook/node-logger": "6.5.13", - "@storybook/semver": "^7.3.2", - "@types/node": "^14.0.10 || ^16.0.0", - "@types/pretty-hrtime": "^1.0.0", - "babel-loader": "^8.0.0", - "babel-plugin-macros": "^3.0.1", - "babel-plugin-polyfill-corejs3": "^0.1.0", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "express": "^4.17.1", - "file-system-cache": "^1.0.5", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.0.4", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "handlebars": "^4.7.7", - "interpret": "^2.2.0", - "json5": "^2.1.3", - "lazy-universal-dotenv": "^3.0.1", - "picomatch": "^2.3.0", - "pkg-dir": "^5.0.0", - "pretty-hrtime": "^1.0.3", - "resolve-from": "^5.0.0", - "slash": "^3.0.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2", - "webpack": "4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-docs/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-docs/node_modules/@storybook/node-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.13.tgz", - "integrity": "sha512-/r5aVZAqZRoy5FyNk/G4pj7yKJd3lJfPbAaOHVROv2IF7PJP/vtRaDkcfh0g2U6zwuDxGIqSn80j+qoEli9m5A==", - "dev": true, - "dependencies": { - "@types/npmlog": "^4.1.2", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "npmlog": "^5.0.1", - "pretty-hrtime": "^1.0.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-docs/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-docs/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-docs/node_modules/@types/node": { - "version": "16.18.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", - "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", - "dev": true - }, - "node_modules/@storybook/addon-docs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@storybook/addon-docs/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", - "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.1.5", - "core-js-compat": "^3.8.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@storybook/addon-docs/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/@storybook/addon-docs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@storybook/addon-docs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@storybook/addon-docs/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/@storybook/addon-docs/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/@storybook/addon-docs/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/@storybook/addon-essentials": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-6.5.13.tgz", - "integrity": "sha512-G9FVAWV7ixjVLWeLgIX+VT90tcAk6yQxfZQegfg5ucRilGysJCDaNnoab4xuuvm1R40TfFhba3iAGZtQYsddmw==", - "dev": true, - "dependencies": { - "@storybook/addon-actions": "6.5.13", - "@storybook/addon-backgrounds": "6.5.13", - "@storybook/addon-controls": "6.5.13", - "@storybook/addon-docs": "6.5.13", - "@storybook/addon-measure": "6.5.13", - "@storybook/addon-outline": "6.5.13", - "@storybook/addon-toolbars": "6.5.13", - "@storybook/addon-viewport": "6.5.13", - "@storybook/addons": "6.5.13", - "@storybook/api": "6.5.13", - "@storybook/core-common": "6.5.13", - "@storybook/node-logger": "6.5.13", - "core-js": "^3.8.2", - "regenerator-runtime": "^0.13.7", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "@babel/core": "^7.9.6" - }, - "peerDependenciesMeta": { - "@storybook/angular": { - "optional": true - }, - "@storybook/builder-manager4": { - "optional": true - }, - "@storybook/builder-manager5": { - "optional": true - }, - "@storybook/builder-webpack4": { - "optional": true - }, - "@storybook/builder-webpack5": { - "optional": true - }, - "@storybook/html": { - "optional": true - }, - "@storybook/vue": { - "optional": true - }, - "@storybook/vue3": { - "optional": true - }, - "@storybook/web-components": { - "optional": true - }, - "lit": { - "optional": true - }, - "lit-html": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "svelte": { - "optional": true - }, - "sveltedoc-parser": { - "optional": true - }, - "vue": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-essentials/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", - "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@storybook/addon-essentials/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-essentials/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-essentials/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-essentials/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-essentials/node_modules/@storybook/core-common": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.5.13.tgz", - "integrity": "sha512-+DVZrRsteE9pw0X5MNffkdBgejQnbnL+UOG3qXkE9xxUamQALnuqS/w1BzpHE9WmOHuf7RWMKflyQEW3OLKAJg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.10", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-decorators": "^7.12.12", - "@babel/plugin-proposal-export-default-from": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.7", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-proposal-private-property-in-object": "^7.12.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.12", - "@babel/plugin-transform-classes": "^7.12.1", - "@babel/plugin-transform-destructuring": "^7.12.1", - "@babel/plugin-transform-for-of": "^7.12.1", - "@babel/plugin-transform-parameters": "^7.12.1", - "@babel/plugin-transform-shorthand-properties": "^7.12.1", - "@babel/plugin-transform-spread": "^7.12.1", - "@babel/preset-env": "^7.12.11", - "@babel/preset-react": "^7.12.10", - "@babel/preset-typescript": "^7.12.7", - "@babel/register": "^7.12.1", - "@storybook/node-logger": "6.5.13", - "@storybook/semver": "^7.3.2", - "@types/node": "^14.0.10 || ^16.0.0", - "@types/pretty-hrtime": "^1.0.0", - "babel-loader": "^8.0.0", - "babel-plugin-macros": "^3.0.1", - "babel-plugin-polyfill-corejs3": "^0.1.0", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "express": "^4.17.1", - "file-system-cache": "^1.0.5", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.0.4", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "handlebars": "^4.7.7", - "interpret": "^2.2.0", - "json5": "^2.1.3", - "lazy-universal-dotenv": "^3.0.1", - "picomatch": "^2.3.0", - "pkg-dir": "^5.0.0", - "pretty-hrtime": "^1.0.3", - "resolve-from": "^5.0.0", - "slash": "^3.0.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2", - "webpack": "4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-essentials/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-essentials/node_modules/@storybook/node-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.13.tgz", - "integrity": "sha512-/r5aVZAqZRoy5FyNk/G4pj7yKJd3lJfPbAaOHVROv2IF7PJP/vtRaDkcfh0g2U6zwuDxGIqSn80j+qoEli9m5A==", - "dev": true, - "dependencies": { - "@types/npmlog": "^4.1.2", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "npmlog": "^5.0.1", - "pretty-hrtime": "^1.0.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-essentials/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-essentials/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-essentials/node_modules/@types/node": { - "version": "16.18.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", - "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", - "dev": true - }, - "node_modules/@storybook/addon-essentials/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@storybook/addon-essentials/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", - "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.1.5", - "core-js-compat": "^3.8.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@storybook/addon-essentials/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/@storybook/addon-essentials/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@storybook/addon-essentials/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@storybook/addon-essentials/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/@storybook/addon-essentials/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/@storybook/addon-essentials/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/@storybook/addon-interactions": { - "version": "6.5.12", - "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-6.5.12.tgz", - "integrity": "sha512-wAkKqUX57qZMzgykMIltjDrFfA0II+pKz2SchK4hXHK3/2rtOe+Ah0Sj5nTQo++Ee5oC1PVZWIq/Y1kufCTBJQ==", - "dev": true, - "dependencies": { - "@devtools-ds/object-inspector": "^1.1.2", - "@storybook/addons": "6.5.12", - "@storybook/api": "6.5.12", - "@storybook/client-logger": "6.5.12", - "@storybook/components": "6.5.12", - "@storybook/core-common": "6.5.12", - "@storybook/core-events": "6.5.12", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/instrumenter": "6.5.12", - "@storybook/theming": "6.5.12", - "core-js": "^3.8.2", - "global": "^4.4.0", - "jest-mock": "^27.0.6", - "polished": "^4.2.2", - "ts-dedent": "^2.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-links": { - "version": "6.5.12", - "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.5.12.tgz", - "integrity": "sha512-Dyt922J5nTBwM/9KtuuDIt3sX8xdTkKh+aXSoOX6OzT04Xwm5NumFOvuQ2YA00EM+3Ihn7Ayc3urvxnHTixmKg==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.12", - "@storybook/client-logger": "6.5.12", - "@storybook/core-events": "6.5.12", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.12", - "@types/qs": "^6.9.5", - "core-js": "^3.8.2", - "global": "^4.4.0", - "prop-types": "^15.7.2", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-measure": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-6.5.13.tgz", - "integrity": "sha512-pi5RFB9YTnESRFtYHAVRUrgEI5to0TFc4KndtwcCKt1fMJ8OFjXQeznEfdj95PFeUvW5TNUwjL38vK4LhicB+g==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/api": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/components": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-measure/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-measure/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-measure/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-measure/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-measure/node_modules/@storybook/components": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.13.tgz", - "integrity": "sha512-6Hhx70JK5pGfKCkqMU4yq/BBH+vRTmzj7tZKfPwba+f8VmTMoOr/2ysTQFRtXryiHB6Z15xBYgfq5x2pIwQzLQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-measure/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-measure/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-measure/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-outline": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-6.5.13.tgz", - "integrity": "sha512-8d8taPheO/tryflzXbj2QRuxHOIS8CtzRzcaglCcioqHEMhOIDOx9BdXKdheq54gdk/UN94HdGJUoVxYyXwZ4Q==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/api": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/components": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-outline/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-outline/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-outline/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-outline/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-outline/node_modules/@storybook/components": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.13.tgz", - "integrity": "sha512-6Hhx70JK5pGfKCkqMU4yq/BBH+vRTmzj7tZKfPwba+f8VmTMoOr/2ysTQFRtXryiHB6Z15xBYgfq5x2pIwQzLQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-outline/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-outline/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-outline/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-toolbars": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-6.5.13.tgz", - "integrity": "sha512-Qgr4wKRSP+gY1VaN7PYT4TM1um7KY341X3GHTglXLFHd8nDsCweawfV2shaX3WxCfZmVro8g4G+Oest30kLLCw==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/api": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/components": "6.5.13", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-toolbars/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-toolbars/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-toolbars/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-toolbars/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-toolbars/node_modules/@storybook/components": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.13.tgz", - "integrity": "sha512-6Hhx70JK5pGfKCkqMU4yq/BBH+vRTmzj7tZKfPwba+f8VmTMoOr/2ysTQFRtXryiHB6Z15xBYgfq5x2pIwQzLQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-toolbars/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-toolbars/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-toolbars/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-viewport": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-6.5.13.tgz", - "integrity": "sha512-KSfeuCSIjncwWGnUu6cZBx8WNqYvm5gHyFvkSPKEu0+MJtgncbUy7pl53lrEEr6QmIq0GRXvS3A0XzV8RCnrSA==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/api": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/components": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "global": "^4.4.0", - "memoizerific": "^1.11.3", - "prop-types": "^15.7.2", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-viewport/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-viewport/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-viewport/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-viewport/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-viewport/node_modules/@storybook/components": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.13.tgz", - "integrity": "sha512-6Hhx70JK5pGfKCkqMU4yq/BBH+vRTmzj7tZKfPwba+f8VmTMoOr/2ysTQFRtXryiHB6Z15xBYgfq5x2pIwQzLQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-viewport/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/addon-viewport/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addon-viewport/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/addons": { - "version": "6.5.12", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.12.tgz", - "integrity": "sha512-y3cgxZq41YGnuIlBJEuJjSFdMsm8wnvlNOGUP9Q+Er2dgfx8rJz4Q22o4hPjpvpaj4XdBtxCJXI2NeFpN59+Cw==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.12", - "@storybook/channels": "6.5.12", - "@storybook/client-logger": "6.5.12", - "@storybook/core-events": "6.5.12", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.12", - "@storybook/theming": "6.5.12", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/api": { - "version": "6.5.12", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.12.tgz", - "integrity": "sha512-DuUZmMlQxkFNU9Vgkp9aNfCkAongU76VVmygvCuSpMVDI9HQ2lG0ydL+ppL4XKoSMCCoXTY6+rg4hJANnH+1AQ==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.12", - "@storybook/client-logger": "6.5.12", - "@storybook/core-events": "6.5.12", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.12", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.12", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/builder-vite": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-0.2.5.tgz", - "integrity": "sha512-0PktEaYsbR6gGE/YDkW/tI1VxVnaPNZpHGpiWfDU7c5hjCajWYzdFTgHOwcXT8tiTs+WN/rvoCPT2iAhSCcHIw==", - "dev": true, - "dependencies": { - "@joshwooding/vite-plugin-react-docgen-typescript": "0.0.5", - "@storybook/core-common": "^6.4.3", - "@storybook/mdx1-csf": "^0.0.4", - "@storybook/node-logger": "^6.4.3", - "@storybook/semver": "^7.3.2", - "@storybook/source-loader": "^6.4.3", - "@vitejs/plugin-react": "^2.0.0", - "ast-types": "^0.14.2", - "es-module-lexer": "^0.9.3", - "glob": "^7.2.0", - "glob-promise": "^4.2.0", - "magic-string": "^0.26.1", - "react-docgen": "^6.0.0-alpha.0", - "slash": "^3.0.0", - "sveltedoc-parser": "^4.2.1" - }, - "peerDependencies": { - "@storybook/mdx2-csf": "^0.0.3", - "@sveltejs/vite-plugin-svelte": "^1.0.0", - "@vitejs/plugin-vue": "^3.0.0", - "vite": ">= 3.0.0", - "vue-docgen-api": "^4.40.0" - }, - "peerDependenciesMeta": { - "@storybook/mdx2-csf": { - "optional": true - }, - "@sveltejs/vite-plugin-svelte": { - "optional": true - }, - "@vitejs/plugin-vue": { - "optional": true - }, - "vue-docgen-api": { - "optional": true - } - } - }, - "node_modules/@storybook/builder-vite/node_modules/@storybook/mdx1-csf": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@storybook/mdx1-csf/-/mdx1-csf-0.0.4.tgz", - "integrity": "sha512-xxUEMy0D+0G1aSYxbeVNbs+XBU5nCqW4I7awpBYSTywXDv/MJWeC6FDRpj5P1pgfq8j8jWDD5ZDvBQ7syFg0LQ==", - "dev": true, - "dependencies": { - "@babel/generator": "^7.12.11", - "@babel/parser": "^7.12.11", - "@babel/preset-env": "^7.12.11", - "@babel/types": "^7.12.11", - "@mdx-js/mdx": "^1.6.22", - "@mdx-js/react": "^1.6.22", - "@types/lodash": "^4.14.167", - "js-string-escape": "^1.0.1", - "loader-utils": "^2.0.0", - "lodash": "^4.17.21", - "prettier": ">=2.2.1 <=2.3.0", - "ts-dedent": "^2.0.0" - } - }, - "node_modules/@storybook/builder-webpack4": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.5.13.tgz", - "integrity": "sha512-Agqy3IKPv3Nl8QqdS7PjtqLp+c0BD8+/3A2ki/YfKqVz+F+J34EpbZlh3uU053avm1EoNQHSmhZok3ZlWH6O7A==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.10", - "@storybook/addons": "6.5.13", - "@storybook/api": "6.5.13", - "@storybook/channel-postmessage": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-api": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/components": "6.5.13", - "@storybook/core-common": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/node-logger": "6.5.13", - "@storybook/preview-web": "6.5.13", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/store": "6.5.13", - "@storybook/theming": "6.5.13", - "@storybook/ui": "6.5.13", - "@types/node": "^14.0.10 || ^16.0.0", - "@types/webpack": "^4.41.26", - "autoprefixer": "^9.8.6", - "babel-loader": "^8.0.0", - "case-sensitive-paths-webpack-plugin": "^2.3.0", - "core-js": "^3.8.2", - "css-loader": "^3.6.0", - "file-loader": "^6.2.0", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^4.1.6", - "glob": "^7.1.6", - "glob-promise": "^3.4.0", - "global": "^4.4.0", - "html-webpack-plugin": "^4.0.0", - "pnp-webpack-plugin": "1.6.4", - "postcss": "^7.0.36", - "postcss-flexbugs-fixes": "^4.2.1", - "postcss-loader": "^4.2.0", - "raw-loader": "^4.0.2", - "stable": "^0.1.8", - "style-loader": "^1.3.0", - "terser-webpack-plugin": "^4.2.3", - "ts-dedent": "^2.0.0", - "url-loader": "^4.1.1", - "util-deprecate": "^1.0.2", - "webpack": "4", - "webpack-dev-middleware": "^3.7.3", - "webpack-filter-warnings-plugin": "^1.2.1", - "webpack-hot-middleware": "^2.25.1", - "webpack-virtual-modules": "^0.2.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", - "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@storybook/components": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.13.tgz", - "integrity": "sha512-6Hhx70JK5pGfKCkqMU4yq/BBH+vRTmzj7tZKfPwba+f8VmTMoOr/2ysTQFRtXryiHB6Z15xBYgfq5x2pIwQzLQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@storybook/core-common": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.5.13.tgz", - "integrity": "sha512-+DVZrRsteE9pw0X5MNffkdBgejQnbnL+UOG3qXkE9xxUamQALnuqS/w1BzpHE9WmOHuf7RWMKflyQEW3OLKAJg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.10", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-decorators": "^7.12.12", - "@babel/plugin-proposal-export-default-from": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.7", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-proposal-private-property-in-object": "^7.12.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.12", - "@babel/plugin-transform-classes": "^7.12.1", - "@babel/plugin-transform-destructuring": "^7.12.1", - "@babel/plugin-transform-for-of": "^7.12.1", - "@babel/plugin-transform-parameters": "^7.12.1", - "@babel/plugin-transform-shorthand-properties": "^7.12.1", - "@babel/plugin-transform-spread": "^7.12.1", - "@babel/preset-env": "^7.12.11", - "@babel/preset-react": "^7.12.10", - "@babel/preset-typescript": "^7.12.7", - "@babel/register": "^7.12.1", - "@storybook/node-logger": "6.5.13", - "@storybook/semver": "^7.3.2", - "@types/node": "^14.0.10 || ^16.0.0", - "@types/pretty-hrtime": "^1.0.0", - "babel-loader": "^8.0.0", - "babel-plugin-macros": "^3.0.1", - "babel-plugin-polyfill-corejs3": "^0.1.0", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "express": "^4.17.1", - "file-system-cache": "^1.0.5", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.0.4", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "handlebars": "^4.7.7", - "interpret": "^2.2.0", - "json5": "^2.1.3", - "lazy-universal-dotenv": "^3.0.1", - "picomatch": "^2.3.0", - "pkg-dir": "^5.0.0", - "pretty-hrtime": "^1.0.3", - "resolve-from": "^5.0.0", - "slash": "^3.0.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2", - "webpack": "4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@storybook/core-common/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/@storybook/builder-webpack4/node_modules/@storybook/core-common/node_modules/fork-ts-checker-webpack-plugin": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", - "integrity": "sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=10", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "eslint": ">= 6", - "typescript": ">= 2.7", - "vue-template-compiler": "*", - "webpack": ">= 4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@storybook/core-common/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@storybook/node-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.13.tgz", - "integrity": "sha512-/r5aVZAqZRoy5FyNk/G4pj7yKJd3lJfPbAaOHVROv2IF7PJP/vtRaDkcfh0g2U6zwuDxGIqSn80j+qoEli9m5A==", - "dev": true, - "dependencies": { - "@types/npmlog": "^4.1.2", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "npmlog": "^5.0.1", - "pretty-hrtime": "^1.0.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@storybook/node-logger/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/@storybook/builder-webpack4/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/@types/node": { - "version": "16.18.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", - "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", - "dev": true - }, - "node_modules/@storybook/builder-webpack4/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", - "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.1.5", - "core-js-compat": "^3.8.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@storybook/builder-webpack4/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/fork-ts-checker-webpack-plugin": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.6.tgz", - "integrity": "sha512-DUxuQaKoqfNne8iikd14SAkh5uw4+8vNifp6gmA73yYNS6ywLIWSLD/n/mBzHQRpW3J7rbATEakmiA8JvkTyZw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.5.5", - "chalk": "^2.4.1", - "micromatch": "^3.1.10", - "minimatch": "^3.0.4", - "semver": "^5.6.0", - "tapable": "^1.0.0", - "worker-rpc": "^0.1.0" - }, - "engines": { - "node": ">=6.11.5", - "yarn": ">=1.0.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@storybook/builder-webpack4/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/@storybook/builder-webpack4/node_modules/glob-promise": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-3.4.0.tgz", - "integrity": "sha512-q08RJ6O+eJn+dVanerAndJwIcumgbDdYiUT7zFQl3Wm1xD6fBKtah7H8ZJChj4wP+8C+QfeVy8xautR7rdmKEw==", - "dev": true, - "dependencies": { - "@types/glob": "*" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "glob": "*" - } - }, - "node_modules/@storybook/builder-webpack4/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/@storybook/builder-webpack4/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/@storybook/builder-webpack4/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/@storybook/builder-webpack4/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/@storybook/builder-webpack4/node_modules/schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/@storybook/builder-webpack4/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/@storybook/builder-webpack4/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/channel-postmessage": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.5.13.tgz", - "integrity": "sha512-R79MBs0mQ7TV8M/a6x/SiTRyvZBidDfMEEthG7Cyo9p35JYiKOhj2535zhW4qlVMESBu95pwKYBibTjASoStPw==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "core-js": "^3.8.2", - "global": "^4.4.0", - "qs": "^6.10.0", - "telejson": "^6.0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/channel-postmessage/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/channel-postmessage/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/channel-postmessage/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/channel-websocket": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-6.5.13.tgz", - "integrity": "sha512-kwh667H+tzCiNvs92GNwYOwVXdj9uHZyieRAN5rJtTBJ7XgLzGkpTEU50mWlbc0nDKhgE0qYvzyr5H393Iy5ug==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "global": "^4.4.0", - "telejson": "^6.0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/channel-websocket/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/channel-websocket/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/channels": { - "version": "6.5.12", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.12.tgz", - "integrity": "sha512-X5XaKbe4b7LXJ4sUakBo00x6pXnW78JkOonHoaKoWsccHLlEzwfBZpVVekhVZnqtCoLT23dB8wjKgA71RYWoiw==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/client-api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.5.13.tgz", - "integrity": "sha512-uH1mAWbidPiuuTdMUVEiuaNOfrYXm+9QLSP1MMYTKULqEOZI5MSOGkEDqRfVWxbYv/iWBOPTQ+OM9TQ6ecYacg==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/channel-postmessage": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/store": "6.5.13", - "@types/qs": "^6.9.5", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "synchronous-promise": "^2.0.15", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/client-api/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/client-api/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/client-api/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/client-api/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/client-api/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/client-api/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/client-api/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/client-logger": { - "version": "6.5.12", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.12.tgz", - "integrity": "sha512-IrkMr5KZcudX935/C2balFbxLHhkvQnJ78rbVThHDVckQ7l3oIXTh66IMzldeOabVFDZEMiW8AWuGEYof+JtLw==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/components": { - "version": "6.5.12", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.12.tgz", - "integrity": "sha512-NAAGl5PDXaHdVLd6hA+ttmLwH3zAVGXeUmEubzKZ9bJzb+duhFKxDa9blM4YEkI+palumvgAMm0UgS7ou680Ig==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.12", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.12", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/core": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core/-/core-6.5.13.tgz", - "integrity": "sha512-kw1lCgbsxzUimGww6t5rmuWJmFPe9kGGyzIqvj4RC4BBcEsP40LEu9XhSfvnb8vTOLIULFZeZpdRFfJs4TYbUw==", - "dev": true, - "dependencies": { - "@storybook/core-client": "6.5.13", - "@storybook/core-server": "6.5.13" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "webpack": "*" - }, - "peerDependenciesMeta": { - "@storybook/builder-webpack5": { - "optional": true - }, - "@storybook/manager-webpack5": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/core-client": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.5.13.tgz", - "integrity": "sha512-YuELbRokTBdqjbx/R4/7O4rou9kvbBIOJjlUkor9hdLLuJ3P0yGianERGNkZFfvcfMBAxU0p52o7QvDldSR3kA==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/channel-postmessage": "6.5.13", - "@storybook/channel-websocket": "6.5.13", - "@storybook/client-api": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/preview-web": "6.5.13", - "@storybook/store": "6.5.13", - "@storybook/ui": "6.5.13", - "airbnb-js-shims": "^2.2.1", - "ansi-to-html": "^0.6.11", - "core-js": "^3.8.2", - "global": "^4.4.0", - "lodash": "^4.17.21", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "ts-dedent": "^2.0.0", - "unfetch": "^4.2.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "webpack": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/core-client/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/core-client/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/core-client/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/core-client/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/core-client/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/core-client/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/core-client/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/core-client/node_modules/ansi-to-html": { - "version": "0.6.15", - "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.15.tgz", - "integrity": "sha512-28ijx2aHJGdzbs+O5SNQF65r6rrKYnkuwTYm8lZlChuoJ9P1vVzIpWO20sQTqTPDXYp6NFwk326vApTtLVFXpQ==", - "dev": true, - "dependencies": { - "entities": "^2.0.0" - }, - "bin": { - "ansi-to-html": "bin/ansi-to-html" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@storybook/core-common": { - "version": "6.5.12", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.5.12.tgz", - "integrity": "sha512-gG20+eYdIhwQNu6Xs805FLrOCWtkoc8Rt8gJiRt8yXzZh9EZkU4xgCRoCxrrJ03ys/gTiCFbBOfRi749uM3z4w==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.10", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-decorators": "^7.12.12", - "@babel/plugin-proposal-export-default-from": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.7", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-proposal-private-property-in-object": "^7.12.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.12", - "@babel/plugin-transform-classes": "^7.12.1", - "@babel/plugin-transform-destructuring": "^7.12.1", - "@babel/plugin-transform-for-of": "^7.12.1", - "@babel/plugin-transform-parameters": "^7.12.1", - "@babel/plugin-transform-shorthand-properties": "^7.12.1", - "@babel/plugin-transform-spread": "^7.12.1", - "@babel/preset-env": "^7.12.11", - "@babel/preset-react": "^7.12.10", - "@babel/preset-typescript": "^7.12.7", - "@babel/register": "^7.12.1", - "@storybook/node-logger": "6.5.12", - "@storybook/semver": "^7.3.2", - "@types/node": "^14.0.10 || ^16.0.0", - "@types/pretty-hrtime": "^1.0.0", - "babel-loader": "^8.0.0", - "babel-plugin-macros": "^3.0.1", - "babel-plugin-polyfill-corejs3": "^0.1.0", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "express": "^4.17.1", - "file-system-cache": "^1.0.5", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.0.4", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "handlebars": "^4.7.7", - "interpret": "^2.2.0", - "json5": "^2.1.3", - "lazy-universal-dotenv": "^3.0.1", - "picomatch": "^2.3.0", - "pkg-dir": "^5.0.0", - "pretty-hrtime": "^1.0.3", - "resolve-from": "^5.0.0", - "slash": "^3.0.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2", - "webpack": "4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/core-common/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", - "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@storybook/core-common/node_modules/@types/node": { - "version": "16.11.62", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.62.tgz", - "integrity": "sha512-K/ggecSdwAAy2NUW4WKmF4Rc03GKbsfP+k326UWgckoS+Rzd2PaWbjk76dSmqdLQvLTJAO9axiTUJ6488mFsYQ==", - "dev": true - }, - "node_modules/@storybook/core-common/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@storybook/core-common/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", - "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.1.5", - "core-js-compat": "^3.8.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@storybook/core-common/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/@storybook/core-common/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@storybook/core-common/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@storybook/core-common/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/@storybook/core-common/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/@storybook/core-common/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/@storybook/core-events": { - "version": "6.5.12", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.12.tgz", - "integrity": "sha512-0AMyMM19R/lHsYRfWqM8zZTXthasTAK2ExkSRzYi2GkIaVMxRKtM33YRwxKIpJ6KmIKIs8Ru3QCXu1mfCmGzNg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/core-server": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.5.13.tgz", - "integrity": "sha512-vs7tu3kAnFwuINio1p87WyqDNlFyZESmeh9s7vvrZVbe/xS/ElqDscr9DT5seW+jbtxufAaHsx+JUTver1dheQ==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "^0.5.3", - "@storybook/builder-webpack4": "6.5.13", - "@storybook/core-client": "6.5.13", - "@storybook/core-common": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/csf-tools": "6.5.13", - "@storybook/manager-webpack4": "6.5.13", - "@storybook/node-logger": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/store": "6.5.13", - "@storybook/telemetry": "6.5.13", - "@types/node": "^14.0.10 || ^16.0.0", - "@types/node-fetch": "^2.5.7", - "@types/pretty-hrtime": "^1.0.0", - "@types/webpack": "^4.41.26", - "better-opn": "^2.1.1", - "boxen": "^5.1.2", - "chalk": "^4.1.0", - "cli-table3": "^0.6.1", - "commander": "^6.2.1", - "compression": "^1.7.4", - "core-js": "^3.8.2", - "cpy": "^8.1.2", - "detect-port": "^1.3.0", - "express": "^4.17.1", - "fs-extra": "^9.0.1", - "global": "^4.4.0", - "globby": "^11.0.2", - "ip": "^2.0.0", - "lodash": "^4.17.21", - "node-fetch": "^2.6.7", - "open": "^8.4.0", - "pretty-hrtime": "^1.0.3", - "prompts": "^2.4.0", - "regenerator-runtime": "^0.13.7", - "serve-favicon": "^2.5.0", - "slash": "^3.0.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2", - "watchpack": "^2.2.0", - "webpack": "4", - "ws": "^8.2.3", - "x-default-browser": "^0.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@storybook/builder-webpack5": { - "optional": true - }, - "@storybook/manager-webpack5": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/core-server/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", - "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@storybook/core-server/node_modules/@storybook/core-common": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.5.13.tgz", - "integrity": "sha512-+DVZrRsteE9pw0X5MNffkdBgejQnbnL+UOG3qXkE9xxUamQALnuqS/w1BzpHE9WmOHuf7RWMKflyQEW3OLKAJg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.10", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-decorators": "^7.12.12", - "@babel/plugin-proposal-export-default-from": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.7", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-proposal-private-property-in-object": "^7.12.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.12", - "@babel/plugin-transform-classes": "^7.12.1", - "@babel/plugin-transform-destructuring": "^7.12.1", - "@babel/plugin-transform-for-of": "^7.12.1", - "@babel/plugin-transform-parameters": "^7.12.1", - "@babel/plugin-transform-shorthand-properties": "^7.12.1", - "@babel/plugin-transform-spread": "^7.12.1", - "@babel/preset-env": "^7.12.11", - "@babel/preset-react": "^7.12.10", - "@babel/preset-typescript": "^7.12.7", - "@babel/register": "^7.12.1", - "@storybook/node-logger": "6.5.13", - "@storybook/semver": "^7.3.2", - "@types/node": "^14.0.10 || ^16.0.0", - "@types/pretty-hrtime": "^1.0.0", - "babel-loader": "^8.0.0", - "babel-plugin-macros": "^3.0.1", - "babel-plugin-polyfill-corejs3": "^0.1.0", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "express": "^4.17.1", - "file-system-cache": "^1.0.5", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.0.4", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "handlebars": "^4.7.7", - "interpret": "^2.2.0", - "json5": "^2.1.3", - "lazy-universal-dotenv": "^3.0.1", - "picomatch": "^2.3.0", - "pkg-dir": "^5.0.0", - "pretty-hrtime": "^1.0.3", - "resolve-from": "^5.0.0", - "slash": "^3.0.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2", - "webpack": "4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/core-server/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/core-server/node_modules/@storybook/node-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.13.tgz", - "integrity": "sha512-/r5aVZAqZRoy5FyNk/G4pj7yKJd3lJfPbAaOHVROv2IF7PJP/vtRaDkcfh0g2U6zwuDxGIqSn80j+qoEli9m5A==", - "dev": true, - "dependencies": { - "@types/npmlog": "^4.1.2", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "npmlog": "^5.0.1", - "pretty-hrtime": "^1.0.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/core-server/node_modules/@types/node": { - "version": "16.18.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", - "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", - "dev": true - }, - "node_modules/@storybook/core-server/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@storybook/core-server/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", - "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.1.5", - "core-js-compat": "^3.8.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@storybook/core-server/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/@storybook/core-server/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@storybook/core-server/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@storybook/core-server/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/@storybook/core-server/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/@storybook/core-server/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/@storybook/csf": { - "version": "0.0.2--canary.4566f4d.1", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.2--canary.4566f4d.1.tgz", - "integrity": "sha512-9OVvMVh3t9znYZwb0Svf/YQoxX2gVOeQTGe2bses2yj+a3+OJnCrUF3/hGv6Em7KujtOdL2LL+JnG49oMVGFgQ==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15" - } - }, - "node_modules/@storybook/csf-tools": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.5.13.tgz", - "integrity": "sha512-63Ev+VmBqzwSwfUzbuXOLKBD5dMTK2zBYLQ9anTVw70FuTikwTsGIbPgb098K0vsxRCgxl7KM7NpivHqtZtdjw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.10", - "@babel/generator": "^7.12.11", - "@babel/parser": "^7.12.11", - "@babel/plugin-transform-react-jsx": "^7.12.12", - "@babel/preset-env": "^7.12.11", - "@babel/traverse": "^7.12.11", - "@babel/types": "^7.12.11", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/mdx1-csf": "^0.0.1", - "core-js": "^3.8.2", - "fs-extra": "^9.0.1", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "@storybook/mdx2-csf": "^0.0.3" - }, - "peerDependenciesMeta": { - "@storybook/mdx2-csf": { - "optional": true - } - } - }, - "node_modules/@storybook/csf-tools/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/@storybook/docs-tools": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-6.5.13.tgz", - "integrity": "sha512-hB+hk+895ny4SW84j3X5iV55DHs3bCfTOp7cDdcZJdQrlm0wuDb4A6d4ffNC7ZLh9VkUjU6ST4VEV5Bb0Cptow==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.10", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/store": "6.5.13", - "core-js": "^3.8.2", - "doctrine": "^3.0.0", - "lodash": "^4.17.21", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/instrumenter": { - "version": "6.5.12", - "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-6.5.12.tgz", - "integrity": "sha512-VMl+Yg6ab79A1VqlhC69sBFI6ySw4Lganqdf9JJf6Y7uNRcZwsjfGpGfYiL4WGH1q72tGiq/25XKGIJV0jgi1Q==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.12", - "@storybook/client-logger": "6.5.12", - "@storybook/core-events": "6.5.12", - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/manager-webpack4": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.5.13.tgz", - "integrity": "sha512-pURzS5W3XM0F7bCBWzpl7TRsuy+OXFwLXiWLaexuvo0POZe31Ueo2A1R4rx3MT5Iee8O9mYvG2XTmvK9MlLefQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.10", - "@babel/plugin-transform-template-literals": "^7.12.1", - "@babel/preset-react": "^7.12.10", - "@storybook/addons": "6.5.13", - "@storybook/core-client": "6.5.13", - "@storybook/core-common": "6.5.13", - "@storybook/node-logger": "6.5.13", - "@storybook/theming": "6.5.13", - "@storybook/ui": "6.5.13", - "@types/node": "^14.0.10 || ^16.0.0", - "@types/webpack": "^4.41.26", - "babel-loader": "^8.0.0", - "case-sensitive-paths-webpack-plugin": "^2.3.0", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "css-loader": "^3.6.0", - "express": "^4.17.1", - "file-loader": "^6.2.0", - "find-up": "^5.0.0", - "fs-extra": "^9.0.1", - "html-webpack-plugin": "^4.0.0", - "node-fetch": "^2.6.7", - "pnp-webpack-plugin": "1.6.4", - "read-pkg-up": "^7.0.1", - "regenerator-runtime": "^0.13.7", - "resolve-from": "^5.0.0", - "style-loader": "^1.3.0", - "telejson": "^6.0.8", - "terser-webpack-plugin": "^4.2.3", - "ts-dedent": "^2.0.0", - "url-loader": "^4.1.1", - "util-deprecate": "^1.0.2", - "webpack": "4", - "webpack-dev-middleware": "^3.7.3", - "webpack-virtual-modules": "^0.2.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/manager-webpack4/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", - "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@storybook/manager-webpack4/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/manager-webpack4/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/manager-webpack4/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/manager-webpack4/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/manager-webpack4/node_modules/@storybook/core-common": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.5.13.tgz", - "integrity": "sha512-+DVZrRsteE9pw0X5MNffkdBgejQnbnL+UOG3qXkE9xxUamQALnuqS/w1BzpHE9WmOHuf7RWMKflyQEW3OLKAJg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.10", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-decorators": "^7.12.12", - "@babel/plugin-proposal-export-default-from": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.7", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-proposal-private-property-in-object": "^7.12.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.12", - "@babel/plugin-transform-classes": "^7.12.1", - "@babel/plugin-transform-destructuring": "^7.12.1", - "@babel/plugin-transform-for-of": "^7.12.1", - "@babel/plugin-transform-parameters": "^7.12.1", - "@babel/plugin-transform-shorthand-properties": "^7.12.1", - "@babel/plugin-transform-spread": "^7.12.1", - "@babel/preset-env": "^7.12.11", - "@babel/preset-react": "^7.12.10", - "@babel/preset-typescript": "^7.12.7", - "@babel/register": "^7.12.1", - "@storybook/node-logger": "6.5.13", - "@storybook/semver": "^7.3.2", - "@types/node": "^14.0.10 || ^16.0.0", - "@types/pretty-hrtime": "^1.0.0", - "babel-loader": "^8.0.0", - "babel-plugin-macros": "^3.0.1", - "babel-plugin-polyfill-corejs3": "^0.1.0", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "express": "^4.17.1", - "file-system-cache": "^1.0.5", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.0.4", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "handlebars": "^4.7.7", - "interpret": "^2.2.0", - "json5": "^2.1.3", - "lazy-universal-dotenv": "^3.0.1", - "picomatch": "^2.3.0", - "pkg-dir": "^5.0.0", - "pretty-hrtime": "^1.0.3", - "resolve-from": "^5.0.0", - "slash": "^3.0.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2", - "webpack": "4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/manager-webpack4/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/manager-webpack4/node_modules/@storybook/node-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.13.tgz", - "integrity": "sha512-/r5aVZAqZRoy5FyNk/G4pj7yKJd3lJfPbAaOHVROv2IF7PJP/vtRaDkcfh0g2U6zwuDxGIqSn80j+qoEli9m5A==", - "dev": true, - "dependencies": { - "@types/npmlog": "^4.1.2", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "npmlog": "^5.0.1", - "pretty-hrtime": "^1.0.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/manager-webpack4/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/manager-webpack4/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/manager-webpack4/node_modules/@types/node": { - "version": "16.18.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", - "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", - "dev": true - }, - "node_modules/@storybook/manager-webpack4/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@storybook/manager-webpack4/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", - "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.1.5", - "core-js-compat": "^3.8.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@storybook/manager-webpack4/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/@storybook/manager-webpack4/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@storybook/manager-webpack4/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@storybook/manager-webpack4/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/@storybook/manager-webpack4/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/@storybook/manager-webpack4/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/@storybook/mdx1-csf": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@storybook/mdx1-csf/-/mdx1-csf-0.0.1.tgz", - "integrity": "sha512-4biZIWWzoWlCarMZmTpqcJNgo/RBesYZwGFbQeXiGYsswuvfWARZnW9RE9aUEMZ4XPn7B1N3EKkWcdcWe/K2tg==", - "dev": true, - "dependencies": { - "@babel/generator": "^7.12.11", - "@babel/parser": "^7.12.11", - "@babel/preset-env": "^7.12.11", - "@babel/types": "^7.12.11", - "@mdx-js/mdx": "^1.6.22", - "@types/lodash": "^4.14.167", - "js-string-escape": "^1.0.1", - "loader-utils": "^2.0.0", - "lodash": "^4.17.21", - "prettier": ">=2.2.1 <=2.3.0", - "ts-dedent": "^2.0.0" - } - }, - "node_modules/@storybook/node-logger": { - "version": "6.5.12", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.12.tgz", - "integrity": "sha512-jdLtT3mX5GQKa+0LuX0q0sprKxtCGf6HdXlKZGD5FEuz4MgJUGaaiN0Hgi+U7Z4tVNOtSoIbYBYXHqfUgJrVZw==", - "dev": true, - "dependencies": { - "@types/npmlog": "^4.1.2", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "npmlog": "^5.0.1", - "pretty-hrtime": "^1.0.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/node-logger/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@storybook/node-logger/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/@storybook/node-logger/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@storybook/node-logger/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@storybook/node-logger/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/@storybook/node-logger/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/@storybook/postinstall": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-6.5.13.tgz", - "integrity": "sha512-qmqP39FGIP5NdhXC5IpAs9cFoYx9fg1psoQKwb9snYb98eVQU31uHc1W2MBUh3lG4AjAm7pQaXJci7ti4jOh3g==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/preview-web": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/preview-web/-/preview-web-6.5.13.tgz", - "integrity": "sha512-GNNYVzw4SmRua3dOc52Ye6Us4iQbq5GKQ56U3iwnzZM3TBdJB+Rft94Fn1/pypHujEHS8hl5Xgp9td6C1lLCow==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/channel-postmessage": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/store": "6.5.13", - "ansi-to-html": "^0.6.11", - "core-js": "^3.8.2", - "global": "^4.4.0", - "lodash": "^4.17.21", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "synchronous-promise": "^2.0.15", - "ts-dedent": "^2.0.0", - "unfetch": "^4.2.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/preview-web/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/preview-web/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/preview-web/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/preview-web/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/preview-web/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/preview-web/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/preview-web/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/preview-web/node_modules/ansi-to-html": { - "version": "0.6.15", - "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.15.tgz", - "integrity": "sha512-28ijx2aHJGdzbs+O5SNQF65r6rrKYnkuwTYm8lZlChuoJ9P1vVzIpWO20sQTqTPDXYp6NFwk326vApTtLVFXpQ==", - "dev": true, - "dependencies": { - "entities": "^2.0.0" - }, - "bin": { - "ansi-to-html": "bin/ansi-to-html" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@storybook/router": { - "version": "6.5.12", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.12.tgz", - "integrity": "sha512-xHubde9YnBbpkDY5+zGO4Pr6VPxP8H9J2v4OTF3H82uaxCIKR0PKG0utS9pFKIsEiP3aM62Hb9qB8nU+v1nj3w==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.12", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/@storybook/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg==", - "dev": true, - "dependencies": { - "core-js": "^3.6.5", - "find-up": "^4.1.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@storybook/semver/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/@storybook/semver/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/@storybook/semver/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/@storybook/semver/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/@storybook/source-loader": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.5.13.tgz", - "integrity": "sha512-tHuM8PfeB/0m+JigbaFp+Ld0euFH+fgOObH2W9rjEXy5vnwmaeex/JAdCprv4oL+LcDQEERqNULUUNIvbcTPAg==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "core-js": "^3.8.2", - "estraverse": "^5.2.0", - "global": "^4.4.0", - "loader-utils": "^2.0.0", - "lodash": "^4.17.21", - "prettier": ">=2.2.1 <=2.3.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/source-loader/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/source-loader/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/source-loader/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/source-loader/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/source-loader/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/source-loader/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/source-loader/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/store": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/store/-/store-6.5.13.tgz", - "integrity": "sha512-GG6lm+8fBX1tNUnX7x3raBOjYhhf14bPWLtYiPlxDTFEMs3sJte7zWKZq6NQ79MoBLL6jjzTeolBfDCBw6fiWQ==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "slash": "^3.0.0", - "stable": "^0.1.8", - "synchronous-promise": "^2.0.15", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/store/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/store/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/store/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/store/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/store/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/store/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/store/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/svelte": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/svelte/-/svelte-6.5.13.tgz", - "integrity": "sha512-QWC7VkHJzwu7BIkxUksDd0mWOvyOaiBgmS1x9dr66tyR+IGXvsoxtujwLMYe/cJuAxwAahphqXy+AmRNwhBLIg==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core": "6.5.13", - "@storybook/core-common": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/docs-tools": "6.5.13", - "@storybook/node-logger": "6.5.13", - "@storybook/store": "6.5.13", - "core-js": "^3.8.2", - "global": "^4.4.0", - "loader-utils": "^2.0.0", - "react": "16.14.0", - "react-dom": "16.14.0", - "read-pkg-up": "^7.0.1", - "regenerator-runtime": "^0.13.7", - "sveltedoc-parser": "4.1.0", - "ts-dedent": "^2.0.0", - "webpack": ">=4.0.0 <6.0.0" - }, - "bin": { - "build-storybook": "bin/build.js", - "start-storybook": "bin/index.js", - "storybook-server": "bin/index.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "@babel/core": "*", - "svelte": "^3.1.0", - "svelte-loader": "*" - }, - "peerDependenciesMeta": { - "svelte-loader": { - "optional": true - } - } - }, - "node_modules/@storybook/svelte/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", - "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@storybook/svelte/node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@storybook/svelte/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/svelte/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/svelte/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/svelte/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/svelte/node_modules/@storybook/core-common": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.5.13.tgz", - "integrity": "sha512-+DVZrRsteE9pw0X5MNffkdBgejQnbnL+UOG3qXkE9xxUamQALnuqS/w1BzpHE9WmOHuf7RWMKflyQEW3OLKAJg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.10", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-decorators": "^7.12.12", - "@babel/plugin-proposal-export-default-from": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.7", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-proposal-private-property-in-object": "^7.12.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.12", - "@babel/plugin-transform-classes": "^7.12.1", - "@babel/plugin-transform-destructuring": "^7.12.1", - "@babel/plugin-transform-for-of": "^7.12.1", - "@babel/plugin-transform-parameters": "^7.12.1", - "@babel/plugin-transform-shorthand-properties": "^7.12.1", - "@babel/plugin-transform-spread": "^7.12.1", - "@babel/preset-env": "^7.12.11", - "@babel/preset-react": "^7.12.10", - "@babel/preset-typescript": "^7.12.7", - "@babel/register": "^7.12.1", - "@storybook/node-logger": "6.5.13", - "@storybook/semver": "^7.3.2", - "@types/node": "^14.0.10 || ^16.0.0", - "@types/pretty-hrtime": "^1.0.0", - "babel-loader": "^8.0.0", - "babel-plugin-macros": "^3.0.1", - "babel-plugin-polyfill-corejs3": "^0.1.0", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "express": "^4.17.1", - "file-system-cache": "^1.0.5", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.0.4", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "handlebars": "^4.7.7", - "interpret": "^2.2.0", - "json5": "^2.1.3", - "lazy-universal-dotenv": "^3.0.1", - "picomatch": "^2.3.0", - "pkg-dir": "^5.0.0", - "pretty-hrtime": "^1.0.3", - "resolve-from": "^5.0.0", - "slash": "^3.0.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2", - "webpack": "4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/svelte/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/svelte/node_modules/@storybook/node-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.13.tgz", - "integrity": "sha512-/r5aVZAqZRoy5FyNk/G4pj7yKJd3lJfPbAaOHVROv2IF7PJP/vtRaDkcfh0g2U6zwuDxGIqSn80j+qoEli9m5A==", - "dev": true, - "dependencies": { - "@types/npmlog": "^4.1.2", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "npmlog": "^5.0.1", - "pretty-hrtime": "^1.0.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/svelte/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/svelte/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/svelte/node_modules/@types/node": { - "version": "16.18.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", - "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", - "dev": true - }, - "node_modules/@storybook/svelte/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/@storybook/svelte/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@storybook/svelte/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", - "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.1.5", - "core-js-compat": "^3.8.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@storybook/svelte/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/@storybook/svelte/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@storybook/svelte/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@storybook/svelte/node_modules/eslint": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.6.0.tgz", - "integrity": "sha512-QlAManNtqr7sozWm5TF4wIH9gmUm2hE3vNRUvyoYAa4y1l5/jxD/PQStEjBMQtCqZmSep8UxrcecI60hOpe61w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.0", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^1.3.0", - "espree": "^7.2.0", - "esquery": "^1.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.19", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@storybook/svelte/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/@storybook/svelte/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/@storybook/svelte/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@storybook/svelte/node_modules/espree": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.2.0.tgz", - "integrity": "sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g==", - "dev": true, - "dependencies": { - "acorn": "^7.3.1", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/@storybook/svelte/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/@storybook/svelte/node_modules/file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "dependencies": { - "flat-cache": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@storybook/svelte/node_modules/flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "dependencies": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@storybook/svelte/node_modules/flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, - "node_modules/@storybook/svelte/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/@storybook/svelte/node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "dependencies": { - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/svelte/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/@storybook/svelte/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@storybook/svelte/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/@storybook/svelte/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@storybook/svelte/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/@storybook/svelte/node_modules/sveltedoc-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sveltedoc-parser/-/sveltedoc-parser-4.1.0.tgz", - "integrity": "sha512-m+NUJaKvVIySRnI19ujYEptxIOHwVvTU2GLKZBVqVQ+zZCrOv/H2F4VtRcjhNKQ/Vd+r7WakxfuUTGxNNdMU3A==", - "dev": true, - "dependencies": { - "eslint": "7.6.0", - "espree": "7.2.0", - "htmlparser2-svelte": "4.1.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@storybook/svelte/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/@storybook/telemetry": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-6.5.13.tgz", - "integrity": "sha512-PFJEfGbunmfFWabD3rdCF8EHH+45578OHOkMPpXJjqXl94vPQxUH2XTVKQgEQJbYrgX0Vx9Z4tSkdMHuzYDbWQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "@storybook/core-common": "6.5.13", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "detect-package-manager": "^2.0.1", - "fetch-retry": "^5.0.2", - "fs-extra": "^9.0.1", - "global": "^4.4.0", - "isomorphic-unfetch": "^3.1.0", - "nanoid": "^3.3.1", - "read-pkg-up": "^7.0.1", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/telemetry/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", - "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, - "node_modules/@storybook/telemetry/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/telemetry/node_modules/@storybook/core-common": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.5.13.tgz", - "integrity": "sha512-+DVZrRsteE9pw0X5MNffkdBgejQnbnL+UOG3qXkE9xxUamQALnuqS/w1BzpHE9WmOHuf7RWMKflyQEW3OLKAJg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.10", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-decorators": "^7.12.12", - "@babel/plugin-proposal-export-default-from": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.7", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-proposal-private-property-in-object": "^7.12.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.12", - "@babel/plugin-transform-classes": "^7.12.1", - "@babel/plugin-transform-destructuring": "^7.12.1", - "@babel/plugin-transform-for-of": "^7.12.1", - "@babel/plugin-transform-parameters": "^7.12.1", - "@babel/plugin-transform-shorthand-properties": "^7.12.1", - "@babel/plugin-transform-spread": "^7.12.1", - "@babel/preset-env": "^7.12.11", - "@babel/preset-react": "^7.12.10", - "@babel/preset-typescript": "^7.12.7", - "@babel/register": "^7.12.1", - "@storybook/node-logger": "6.5.13", - "@storybook/semver": "^7.3.2", - "@types/node": "^14.0.10 || ^16.0.0", - "@types/pretty-hrtime": "^1.0.0", - "babel-loader": "^8.0.0", - "babel-plugin-macros": "^3.0.1", - "babel-plugin-polyfill-corejs3": "^0.1.0", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "express": "^4.17.1", - "file-system-cache": "^1.0.5", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.0.4", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "handlebars": "^4.7.7", - "interpret": "^2.2.0", - "json5": "^2.1.3", - "lazy-universal-dotenv": "^3.0.1", - "picomatch": "^2.3.0", - "pkg-dir": "^5.0.0", - "pretty-hrtime": "^1.0.3", - "resolve-from": "^5.0.0", - "slash": "^3.0.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2", - "webpack": "4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/telemetry/node_modules/@storybook/node-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.13.tgz", - "integrity": "sha512-/r5aVZAqZRoy5FyNk/G4pj7yKJd3lJfPbAaOHVROv2IF7PJP/vtRaDkcfh0g2U6zwuDxGIqSn80j+qoEli9m5A==", - "dev": true, - "dependencies": { - "@types/npmlog": "^4.1.2", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "npmlog": "^5.0.1", - "pretty-hrtime": "^1.0.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/telemetry/node_modules/@types/node": { - "version": "16.18.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", - "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", - "dev": true - }, - "node_modules/@storybook/telemetry/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@storybook/telemetry/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", - "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.1.5", - "core-js-compat": "^3.8.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@storybook/telemetry/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/@storybook/telemetry/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@storybook/telemetry/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@storybook/telemetry/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/@storybook/telemetry/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/@storybook/telemetry/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/@storybook/testing-library": { - "version": "0.0.13", - "resolved": "https://registry.npmjs.org/@storybook/testing-library/-/testing-library-0.0.13.tgz", - "integrity": "sha512-vRMeIGer4EjJkTgI8sQyK9W431ekPWYCWL//OmSDJ64IT3h7FnW7Xg6p+eqM3oII98/O5pcya5049GxnjaPtxw==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "^6.4.0", - "@storybook/instrumenter": "^6.4.0", - "@testing-library/dom": "^8.3.0", - "@testing-library/user-event": "^13.2.1", - "ts-dedent": "^2.2.0" - } - }, - "node_modules/@storybook/theming": { - "version": "6.5.12", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.12.tgz", - "integrity": "sha512-uWOo84qMQ2R6c1C0faZ4Q0nY01uNaX7nXoJKieoiJ6ZqY9PSYxJl1kZLi3uPYnrxLZjzjVyXX8MgdxzbppYItA==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.12", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/ui": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/ui/-/ui-6.5.13.tgz", - "integrity": "sha512-MklJuSg4Bc+MWjwhZVmZhJaucaeEBUMMa2V9oRWbIgZOdRHqdW72S2vCbaarDAYfBQdnfaoq1GkSQiw+EnWOzA==", - "dev": true, - "dependencies": { - "@storybook/addons": "6.5.13", - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/components": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "resolve-from": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/ui/node_modules/@storybook/addons": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.13.tgz", - "integrity": "sha512-18CqzNnrGMfeZtiKz+R/3rHtSNnfNwz6y6prIQIbWseK16jY8ELTfIFGviwO5V2OqpbHDQi5+xQQ63QAIb89YA==", - "dev": true, - "dependencies": { - "@storybook/api": "6.5.13", - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/theming": "6.5.13", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/ui/node_modules/@storybook/api": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.13.tgz", - "integrity": "sha512-xVSmB7/IuFd6G7eiJjbI2MuS7SZunoUM6d+YCWpjiehfMeX47MXt1gZtOwFrgJC1ShZlefXFahq/dvxwtmWs+w==", - "dev": true, - "dependencies": { - "@storybook/channels": "6.5.13", - "@storybook/client-logger": "6.5.13", - "@storybook/core-events": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.13", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/ui/node_modules/@storybook/channels": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.13.tgz", - "integrity": "sha512-sGYSilE30bz0jG+HdHnkv0B4XkAv2hP+KRZr4xmnv+MOOQpRnZpJ5Z3HVU16s17cj/83NWihKj6BuKcEVzyilg==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/ui/node_modules/@storybook/client-logger": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.13.tgz", - "integrity": "sha512-F2SMW3LWFGXLm2ENTwTitrLWJgmMXRf3CWQXdN2EbkNCIBHy5Zcbt+91K4OX8e2e5h9gjGfrdYbyYDYOoUCEfA==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/ui/node_modules/@storybook/components": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.13.tgz", - "integrity": "sha512-6Hhx70JK5pGfKCkqMU4yq/BBH+vRTmzj7tZKfPwba+f8VmTMoOr/2ysTQFRtXryiHB6Z15xBYgfq5x2pIwQzLQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/ui/node_modules/@storybook/core-events": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.13.tgz", - "integrity": "sha512-kL745tPpRKejzHToA3/CoBNbI+NPRVk186vGxXBmk95OEg0TlwgQExP8BnqEtLlRZMbW08e4+6kilc1M1M4N5w==", - "dev": true, - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/ui/node_modules/@storybook/router": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.13.tgz", - "integrity": "sha512-sf5aogfirH5ucD0d0hc2mKf2iyWsZsvXhr5kjxUQmgkcoflkGUWhc34sbSQVRQ1i8K5lkLIDH/q2s1Zr2SbzhQ==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/ui/node_modules/@storybook/theming": { - "version": "6.5.13", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.13.tgz", - "integrity": "sha512-oif5NGFAUQhizo50r+ctw2hZNLWV4dPHai+L/gFvbaSeRBeHSNkIcMoZ2FlrO566HdGZTDutYXcR+xus8rI28g==", - "dev": true, - "dependencies": { - "@storybook/client-logger": "6.5.13", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.8.tgz", - "integrity": "sha512-1xkVTB4pm6zuign858FzVYE9Fdw9MQBOlxrdd85STV0NvTDmcofcRpcrK+zcIyT8SZ2dseHLu8hvDwzssF6RfA==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^4.2.1", - "debug": "^4.3.4", - "deepmerge": "^4.2.2", - "kleur": "^4.1.5", - "magic-string": "^0.26.3", - "svelte-hmr": "^0.15.0" - }, - "engines": { - "node": "^14.18.0 || >= 16" - }, - "peerDependencies": { - "diff-match-patch": "^1.0.5", - "svelte": "^3.44.0", - "vite": "^3.0.0" - }, - "peerDependenciesMeta": { - "diff-match-patch": { - "optional": true - } - } - }, - "node_modules/@testing-library/dom": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.18.1.tgz", - "integrity": "sha512-oEvsm2B/WtcHKE+IcEeeCqNU/ltFGaVyGbpcm4g/2ytuT49jrlH9x5qRKL/H3A6yfM4YAbSbC0ceT5+9CEXnLg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^4.2.0", - "aria-query": "^5.0.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.4.4", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@testing-library/dom/node_modules/@babel/runtime": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz", - "integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@testing-library/dom/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@testing-library/dom/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/@testing-library/dom/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@testing-library/dom/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@testing-library/dom/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/@testing-library/dom/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/@testing-library/user-event": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", - "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - }, - "peerDependencies": { - "@testing-library/dom": ">=7.21.4" - } - }, - "node_modules/@testing-library/user-event/node_modules/@babel/runtime": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz", - "integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@types/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", - "dev": true - }, - "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/hast": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", - "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", - "dev": true, - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/html-minifier-terser": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz", - "integrity": "sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==", - "dev": true - }, - "node_modules/@types/is-function": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/is-function/-/is-function-1.0.1.tgz", - "integrity": "sha512-A79HEEiwXTFtfY+Bcbo58M2GRYzCr9itHWzbzHVFNEYCcoU/MMGwYYf721gBrnhpj1s6RGVVha/IgNFnR0Iw/Q==", - "dev": true - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/lodash": { - "version": "4.14.186", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.186.tgz", - "integrity": "sha512-eHcVlLXP0c2FlMPm56ITode2AgLMSa6aJ05JTTbYbI+7EMkCEE5qk2E41d5g2lCVTqRe0GnnRFurmlCsDODrPw==", - "dev": true - }, - "node_modules/@types/mdast": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", - "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", - "dev": true, - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.7.23", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.23.tgz", - "integrity": "sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg==", - "dev": true - }, - "node_modules/@types/node-fetch": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", - "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", - "dev": true, - "dependencies": { - "@types/node": "*", - "form-data": "^3.0.0" - } - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "node_modules/@types/npmlog": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.4.tgz", - "integrity": "sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==", - "dev": true - }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "node_modules/@types/parse5": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", - "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==", - "dev": true - }, - "node_modules/@types/pretty-hrtime": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.1.tgz", - "integrity": "sha512-VjID5MJb1eGKthz2qUerWT8+R4b9N+CHvGCzg9fn4kWZgaF9AhdYikQio3R7wV8YY1NsQKPaCwKz1Yff+aHNUQ==", - "dev": true - }, - "node_modules/@types/prop-types": { - "version": "15.7.5", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", - "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", - "dev": true, - "peer": true - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "node_modules/@types/react": { - "version": "18.0.25", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.25.tgz", - "integrity": "sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g==", - "dev": true, - "peer": true, - "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", - "dev": true, - "peer": true - }, - "node_modules/@types/source-list-map": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", - "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", - "dev": true - }, - "node_modules/@types/tapable": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", - "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==", - "dev": true - }, - "node_modules/@types/uglify-js": { - "version": "3.17.1", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.17.1.tgz", - "integrity": "sha512-GkewRA4i5oXacU/n4MA9+bLgt5/L3F1mKrYvFGm7r2ouLXhRKjuWwo9XHNnbx6WF3vlGW21S3fCvgqxvxXXc5g==", - "dev": true, - "dependencies": { - "source-map": "^0.6.1" - } - }, - "node_modules/@types/unist": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", - "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", - "dev": true - }, - "node_modules/@types/webpack": { - "version": "4.41.33", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.33.tgz", - "integrity": "sha512-PPajH64Ft2vWevkerISMtnZ8rTs4YmRbs+23c402J0INmxDKCrhZNvwZYtzx96gY2wAtXdrK1BS2fiC8MlLr3g==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/tapable": "^1", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "anymatch": "^3.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/@types/webpack-env": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.0.tgz", - "integrity": "sha512-56/MAlX5WMsPVbOg7tAxnYvNYMMWr/QJiIp6BxVSW3JJXUVzzOn64qW8TzQyMSqSUFM2+PVI4aUHcHOzIz/1tg==", - "dev": true - }, - "node_modules/@types/webpack-sources": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", - "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/source-list-map": "*", - "source-map": "^0.7.3" - } - }, - "node_modules/@types/webpack-sources/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/yargs": { - "version": "15.0.14", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", - "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "node_modules/@vitejs/plugin-react": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-2.1.0.tgz", - "integrity": "sha512-am6rPyyU3LzUYne3Gd9oj9c4Rzbq5hQnuGXSMT6Gujq45Il/+bunwq3lrB7wghLkiF45ygMwft37vgJ/NE8IAA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.18.13", - "@babel/plugin-transform-react-jsx": "^7.18.10", - "@babel/plugin-transform-react-jsx-development": "^7.18.6", - "@babel/plugin-transform-react-jsx-self": "^7.18.6", - "@babel/plugin-transform-react-jsx-source": "^7.18.6", - "magic-string": "^0.26.2", - "react-refresh": "^0.14.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^3.0.0" - } - }, - "node_modules/@vusion/webfonts-generator": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@vusion/webfonts-generator/-/webfonts-generator-0.8.0.tgz", - "integrity": "sha512-1q17CF6umBEjlAtO37TzRw3aOCCAyFX+T4HPG70BmM6qx8s6H4/LQOa8eHFZq/oiMuMyd0FehKgUt/pqYlIMWA==", - "dependencies": { - "handlebars": "^4.0.11", - "mkdirp": "^1.0.4", - "q": "^1.1.2", - "svg2ttf": "^6.0.3", - "svgicons2svgfont": "^10.0.4", - "ttf2eot": "^3.0.0", - "ttf2woff": "^3.0.0", - "ttf2woff2": "^4.0.4", - "underscore": "^1.9.1", - "url-join": "^4.0.0" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", - "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", - "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", - "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-code-frame": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", - "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", - "dev": true, - "dependencies": { - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "node_modules/@webassemblyjs/helper-fsm": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", - "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-module-context": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", - "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", - "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", - "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", - "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", - "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", - "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/helper-wasm-section": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-opt": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", - "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", - "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", - "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "node_modules/@webassemblyjs/wast-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", - "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/floating-point-hex-parser": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-code-frame": "1.9.0", - "@webassemblyjs/helper-fsm": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", - "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.7.9", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.9.tgz", - "integrity": "sha512-yceMpm/xd4W2a85iqZyO09gTnHvXF6pyiWjD2jcOJs7hRoZtNNOO1eJlhHj1ixA+xip2hOyGn+LgcvLCMo5zXA==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": 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/address": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.1.tgz", - "integrity": "sha512-B+6bi5D34+fDYENiH5qOlA0cV2rAGKuWZ9LeyUUehbXy8e0VS9e498yO0Jeeh+iM+6KbfudHTFjXw2MmJD4QRA==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agentkeepalive": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", - "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", - "dependencies": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/agentkeepalive/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/airbnb-js-shims": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/airbnb-js-shims/-/airbnb-js-shims-2.2.1.tgz", - "integrity": "sha512-wJNXPH66U2xjgo1Zwyjf9EydvJ2Si94+vSdk6EERcBfB2VZkeltpqIats0cqIZMLCXP3zcyaUKGYQeIBT6XjsQ==", - "dev": true, - "dependencies": { - "array-includes": "^3.0.3", - "array.prototype.flat": "^1.2.1", - "array.prototype.flatmap": "^1.2.1", - "es5-shim": "^4.5.13", - "es6-shim": "^0.35.5", - "function.prototype.name": "^1.1.0", - "globalthis": "^1.0.0", - "object.entries": "^1.1.0", - "object.fromentries": "^2.0.0 || ^1.0.0", - "object.getownpropertydescriptors": "^2.0.3", - "object.values": "^1.1.0", - "promise.allsettled": "^1.0.0", - "promise.prototype.finally": "^3.1.0", - "string.prototype.matchall": "^4.0.0 || ^3.0.1", - "string.prototype.padend": "^3.0.0", - "string.prototype.padstart": "^3.0.0", - "symbol.prototype.description": "^1.0.0" - } - }, - "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/ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true, - "peerDependencies": { - "ajv": ">=5.0.0" - } - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "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": "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/ansi-to-html": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.7.2.tgz", - "integrity": "sha512-v6MqmEpNlxF+POuyhKkidusCHWWkaLcGRURzivcU3I9tv7k4JVhFcnukrM5Rlk2rUywdZuzYAZ+kbZqWCnfN3g==", - "dependencies": { - "entities": "^2.2.0" - }, - "bin": { - "ansi-to-html": "bin/ansi-to-html" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/app-root-dir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/app-root-dir/-/app-root-dir-1.0.2.tgz", - "integrity": "sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g==", - "dev": true - }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "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/aria-query": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.2.tgz", - "integrity": "sha512-eigU3vhqSO+Z8BKDnVLN/ompjhf3pYzecKXz8+whRy+9gZu8n1TCGfwzQUUPnqdHl9ax1Hr9031orZ+UOEYr7Q==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "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-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "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.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.map": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.5.tgz", - "integrity": "sha512-gfaKntvwqYIuC7mLLyv2wzZIJqrRhn5PZ9EfFejSx6a78sV7iDsGpG9P+3oUPtm1Rerqm6nrKS4FYuTIvWfo3g==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.reduce": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz", - "integrity": "sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "dependencies": { - "object-assign": "^4.1.1", - "util": "0.10.3" - } - }, - "node_modules/assert/node_modules/inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", - "dev": true - }, - "node_modules/assert/node_modules/util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", - "dev": true, - "dependencies": { - "inherits": "2.0.1" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ast-types": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", - "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", - "dev": true, - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true, - "optional": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "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/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/autoprefixer": { - "version": "9.8.8", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", - "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", - "dev": true, - "dependencies": { - "browserslist": "^4.12.0", - "caniuse-lite": "^1.0.30001109", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "picocolors": "^0.2.1", - "postcss": "^7.0.32", - "postcss-value-parser": "^4.1.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "funding": { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - } - }, - "node_modules/autoprefixer/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/autoprefixer/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/babel-loader": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.5.tgz", - "integrity": "sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ==", - "dev": true, - "dependencies": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" - }, - "engines": { - "node": ">= 8.9" - }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "webpack": ">=2" - } - }, - "node_modules/babel-loader/node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/babel-loader/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/babel-loader/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/babel-loader/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/babel-loader/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/babel-loader/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/babel-loader/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/babel-plugin-apply-mdx-type-prop": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz", - "integrity": "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "7.10.4", - "@mdx-js/util": "1.6.22" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@babel/core": "^7.11.6" - } - }, - "node_modules/babel-plugin-apply-mdx-type-prop/node_modules/@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", - "dev": true - }, - "node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "dependencies": { - "object.assign": "^4.1.0" - } - }, - "node_modules/babel-plugin-extract-import-names": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", - "integrity": "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "7.10.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/babel-plugin-extract-import-names/node_modules/@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", - "dev": true - }, - "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-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - } - }, - "node_modules/babel-plugin-macros/node_modules/@babel/runtime": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz", - "integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", - "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-define-polyfill-provider": "^0.3.3", - "semver": "^6.1.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", - "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3", - "core-js-compat": "^3.25.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", - "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/bail": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", - "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "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/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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/better-opn": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-2.1.1.tgz", - "integrity": "sha512-kIPXZS5qwyKiX/HcRvDYfmBQUa8XP17I0mYZZ0y4UhpYOSvtsLHDYqmomS+Mj20aDvD3knEiQ0ecQy2nhio3yA==", - "dev": true, - "dependencies": { - "open": "^7.0.3" - }, - "engines": { - "node": ">8.0.0" - } - }, - "node_modules/better-opn/node_modules/open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", - "dev": true - }, - "node_modules/body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.10.3", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "dev": true, - "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/boxen/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/boxen/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/boxen/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/boxen/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/boxen/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/boxen/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/bplist-parser": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.1.1.tgz", - "integrity": "sha512-2AEM0FXy8ZxVLBuqX0hqt1gDwcnz2zygEkQ6zaD5Wko/sB9paUNwlpawrFtKeHUAQUOzjVy9AO4oeonqIHKA9Q==", - "dev": true, - "optional": true, - "dependencies": { - "big-integer": "^1.6.7" - } - }, - "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==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "dev": true - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "node_modules/browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "dev": true, - "dependencies": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dev": true, - "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "node_modules/browserify-sign/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/browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "dependencies": { - "pako": "~1.0.5" - } - }, - "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - }, - "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": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", - "dev": true - }, - "node_modules/buffer/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/bufferstreams": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-3.0.0.tgz", - "integrity": "sha512-Qg0ggJUWJq90vtg4lDsGN9CDWvzBMQxhiEkSOD/sJfYt6BLect3eV1/S6K7SCSKJ34n60rf6U5eUPmQENVE4UA==", - "dependencies": { - "readable-stream": "^3.4.0" - }, - "engines": { - "node": ">=8.12.0" - } - }, - "node_modules/builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", - "dev": true - }, - "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/c8": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.12.0.tgz", - "integrity": "sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^2.0.0", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-reports": "^3.1.4", - "rimraf": "^3.0.2", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.0.0", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "dev": true, - "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cacache/node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", - "dev": true - }, - "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/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "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/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==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/camelcase-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-1.0.0.tgz", - "integrity": "sha512-hwNYKTjJTlDabjJp2xn0h8bRmOpObvXVgYbQmR+Xob/EeBDtYea3xttjr5hqiWqLWtI3/6xO7x1ZAktQ9up+ag==", - "dev": true, - "optional": true, - "dependencies": { - "camelcase": "^1.0.1", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/camelcase-keys/node_modules/camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001414", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001414.tgz", - "integrity": "sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ] - }, - "node_modules/capture-exit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", - "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", - "dev": true, - "dependencies": { - "rsvp": "^4.8.4" - }, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ccount": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", - "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "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/character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chart.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.2.0.tgz", - "integrity": "sha512-wbtcV+QKeH0F7gQZaCJEIpsNriFheacouJQTVIjITi3eQA8bTlIBoknz0+dgV79aeKLNMAX+nDslIVE/nJ3rzA==", - "dependencies": { - "@kurkle/color": "^0.3.0" - }, - "engines": { - "pnpm": "^7.0.0" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "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" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/class-utils/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/clean-css": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", - "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", - "dev": true, - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clsx": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.0.tgz", - "integrity": "sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/collapse-white-space": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", - "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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/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/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/comma-separated-tokens": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", - "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/concat-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/concat-stream/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/concat-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", - "dev": true - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" - }, - "node_modules/constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", - "dev": true - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-disposition/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/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "node_modules/copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "dependencies": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "node_modules/copy-concurrently/node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "node_modules/copy-concurrently/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/copy-concurrently/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/core-js": { - "version": "3.25.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.3.tgz", - "integrity": "sha512-y1hvKXmPHvm5B7w4ln1S4uc9eV/O5+iFExSRUimnvIph11uaizFR8LFMdONN8hG3P2pipUfX4Y/fR8rAEtcHcQ==", - "dev": true, - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-compat": { - "version": "3.25.3", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.3.tgz", - "integrity": "sha512-xVtYpJQ5grszDHEUU9O7XbjjcZ0ccX3LgQsyqSvTnjX97ZqEgn9F5srmrwwwMtbKzDllyFPL+O+2OFMl1lU4TQ==", - "dev": true, - "dependencies": { - "browserslist": "^4.21.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cp-file": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-7.0.0.tgz", - "integrity": "sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "nested-error-stacks": "^2.0.0", - "p-event": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cp-file/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cpy": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/cpy/-/cpy-8.1.2.tgz", - "integrity": "sha512-dmC4mUesv0OYH2kNFEidtf/skUwv4zePmGeepjyyJ0qTo5+8KhA1o99oIAwVVLzQMAeDJml74d6wPPKb6EZUTg==", - "dev": true, - "dependencies": { - "arrify": "^2.0.1", - "cp-file": "^7.0.0", - "globby": "^9.2.0", - "has-glob": "^1.0.0", - "junk": "^3.1.0", - "nested-error-stacks": "^2.1.0", - "p-all": "^2.1.0", - "p-filter": "^2.1.0", - "p-map": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cpy/node_modules/@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cpy/node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", - "dev": true, - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cpy/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cpy/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cpy/node_modules/dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", - "dev": true, - "dependencies": { - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cpy/node_modules/fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", - "dev": true, - "dependencies": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/cpy/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cpy/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cpy/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", - "dev": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/cpy/node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cpy/node_modules/globby": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", - "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^1.0.2", - "dir-glob": "^2.2.2", - "fast-glob": "^2.2.6", - "glob": "^7.1.3", - "ignore": "^4.0.3", - "pify": "^4.0.1", - "slash": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cpy/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/cpy/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/cpy/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cpy/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cpy/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cpy/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cpy/node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cpy/node_modules/path-type/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/cpy/node_modules/slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cpy/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, - "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "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==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/css-loader": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", - "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "cssesc": "^3.0.0", - "icss-utils": "^4.1.1", - "loader-utils": "^1.2.3", - "normalize-path": "^3.0.0", - "postcss": "^7.0.32", - "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^3.0.2", - "postcss-modules-scope": "^2.2.0", - "postcss-modules-values": "^3.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^2.7.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/css-loader/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/css-loader/node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/css-loader/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/css-loader/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "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/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssstyle": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", - "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@asamuzakjp/css-color": "^3.2.0", - "rrweb-cssom": "^0.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cssstyle/node_modules/rrweb-cssom": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", - "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", - "dev": true, - "license": "MIT" - }, - "node_modules/csstype": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", - "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", - "dev": true, - "peer": true - }, - "node_modules/cubic2quad": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/cubic2quad/-/cubic2quad-1.2.1.tgz", - "integrity": "sha512-wT5Y7mO8abrV16gnssKdmIhIbA9wSkeMzhh27jAguKrV82i24wER0vL5TGhUJ9dbJNDcigoRZ0IAHFEEEI4THQ==" - }, - "node_modules/cyclist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", - "integrity": "sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==", - "dev": true - }, - "node_modules/data-urls": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", - "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/data-urls/node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/data-urls/node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/data-urls/node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decimal.js": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", - "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", - "dev": true, - "license": "MIT" - }, - "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/dedent-js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz", - "integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==" - }, - "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.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-browser-id": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-1.0.4.tgz", - "integrity": "sha512-qPy925qewwul9Hifs+3sx1ZYn14obHxpkX+mPD369w4Rzg+YkJBgi3SOvwUq81nWSjqGUegIgEPwD8u+HUnxlw==", - "dev": true, - "optional": true, - "dependencies": { - "bplist-parser": "^0.1.0", - "meow": "^3.1.0", - "untildify": "^2.0.0" - }, - "bin": { - "default-browser-id": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "dev": true, - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detab": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz", - "integrity": "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==", - "dev": true, - "dependencies": { - "repeat-string": "^1.5.4" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/detect-package-manager": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-package-manager/-/detect-package-manager-2.0.1.tgz", - "integrity": "sha512-j/lJHyoLlWi6G1LDdLgvUtz60Zo5GEj+sVYtTVXnYLDPuzgC3llMxonXym9zIwhhUII8vjdw0LXxavpLqTbl1A==", - "dev": true, - "dependencies": { - "execa": "^5.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/detect-port": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", - "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", - "dev": true, - "dependencies": { - "address": "^1.0.1", - "debug": "4" - }, - "bin": { - "detect": "bin/detect-port.js", - "detect-port": "bin/detect-port.js" - } - }, - "node_modules/diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/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/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.14", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.14.tgz", - "integrity": "sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==", - "dev": true - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", - "dev": true - }, - "node_modules/domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true, - "engines": { - "node": ">=0.4", - "npm": ">=1.2" - } - }, - "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": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "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/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", - "dev": true - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/duplexify/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/duplexify/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/duplexify/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.268", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.268.tgz", - "integrity": "sha512-PO90Bv++vEzdln+eA9qLg1IRnh0rKETus6QkTzcFm5P3Wg3EQBZud5dcnzkpYXuIKWBjKe5CO8zjz02cicvn1g==", - "dev": true - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/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/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/enhanced-resolve/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/enhanced-resolve/node_modules/memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - }, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, - "node_modules/enhanced-resolve/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/enhanced-resolve/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "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==", - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" - }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "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.20.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.4.tgz", - "integrity": "sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "license": "MIT", - "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, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-get-iterator": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz", - "integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.0", - "has-symbols": "^1.0.1", - "is-arguments": "^1.1.0", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.5", - "isarray": "^2.0.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - } - }, - "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/es5-shim": { - "version": "4.6.7", - "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.6.7.tgz", - "integrity": "sha512-jg21/dmlrNQI7JyyA2w7n+yifSxBng0ZralnSfVZjoCawgNTCnS+yBCyVM9DL5itm7SUnDGgv7hcq2XCZX4iRQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/es6-shim": { - "version": "0.35.6", - "resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.6.tgz", - "integrity": "sha512-EmTr31wppcaIAgblChZiuN/l9Y7DPyw8Xtbg7fIVngn6zMW+IEBJDJngeKC3x6wr0V/vcA2wqeFnaw1bFJbDdA==", - "dev": true - }, - "node_modules/esbuild": { - "version": "0.15.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.9.tgz", - "integrity": "sha512-OnYr1rkMVxtmMHIAKZLMcEUlJmqcbxBz9QoBU8G9v455na0fuzlT/GLu6l+SRghrk0Mm2fSSciMmzV43Q8e0Gg==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.15.9", - "@esbuild/linux-loong64": "0.15.9", - "esbuild-android-64": "0.15.9", - "esbuild-android-arm64": "0.15.9", - "esbuild-darwin-64": "0.15.9", - "esbuild-darwin-arm64": "0.15.9", - "esbuild-freebsd-64": "0.15.9", - "esbuild-freebsd-arm64": "0.15.9", - "esbuild-linux-32": "0.15.9", - "esbuild-linux-64": "0.15.9", - "esbuild-linux-arm": "0.15.9", - "esbuild-linux-arm64": "0.15.9", - "esbuild-linux-mips64le": "0.15.9", - "esbuild-linux-ppc64le": "0.15.9", - "esbuild-linux-riscv64": "0.15.9", - "esbuild-linux-s390x": "0.15.9", - "esbuild-netbsd-64": "0.15.9", - "esbuild-openbsd-64": "0.15.9", - "esbuild-sunos-64": "0.15.9", - "esbuild-windows-32": "0.15.9", - "esbuild-windows-64": "0.15.9", - "esbuild-windows-arm64": "0.15.9" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.15.9", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.9.tgz", - "integrity": "sha512-4RXjae7g6Qs7StZyiYyXTZXBlfODhb1aBVAjd+ANuPmMhWthQilWo7rFHwJwL7DQu1Fjej2sODAVwLbcIVsAYQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "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/eslint": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.4.1.tgz", - "integrity": "sha512-TxU/p7LB1KxQ6+7aztTnO7K0i+h0tDi81YRY9VzB6Id71kNz+fFYnf5HD5UOQmxkzcoa0TlVZf9dpMtUv0GpWg==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^1.0.5", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.2.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.2.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "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-plugin-svelte3": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte3/-/eslint-plugin-svelte3-4.0.0.tgz", - "integrity": "sha512-OIx9lgaNzD02+MDFNLw0GEUbuovNcglg+wnd/UY0fbZmlQSz7GlQiQ1f+yX0XvC07XPcDOnFcichqI3xCwp71g==", - "dev": true, - "peerDependencies": { - "eslint": ">=8.0.0", - "svelte": "^3.2.0" - } - }, - "node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/eslint/node_modules/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/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", - "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/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/espree": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz", - "integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==", - "dev": true, - "dependencies": { - "acorn": "^8.6.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "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.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "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/estree-to-babel": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/estree-to-babel/-/estree-to-babel-3.2.1.tgz", - "integrity": "sha512-YNF+mZ/Wu2FU/gvmzuWtYc8rloubL7wfXCTgouFrnjGVXPA/EeYYA7pupXWrb3Iv1cTBeSSxxJIbK23l4MRNqg==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.1.6", - "@babel/types": "^7.2.0", - "c8": "^7.6.0" - }, - "engines": { - "node": ">=8.3.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "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/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/exec-sh": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz", - "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==", - "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/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.0", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.10.3", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/express/node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/express/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/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "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-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "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-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/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "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/fetch-retry": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-5.0.3.tgz", - "integrity": "sha512-uJQyMrX5IJZkhoEUBQ3EjxkeiZkppBd5jS/fMTJmfZxLSiaQjv2zD0kTvuvkSH89uFvgSlB6ueGpjD3HWN7Bxw==", - "dev": true - }, - "node_modules/figgy-pudding": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", - "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", - "dev": true - }, - "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/file-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", - "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", - "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/file-loader/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/file-system-cache": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-1.1.0.tgz", - "integrity": "sha512-IzF5MBq+5CR0jXx5RxPe4BICl/oEhBSXKaL9fLhAXrIfIUS77Hr4vzrYyqYMHN6uTt+BOqi3fDCTjjEBCjERKw==", - "dev": true, - "dependencies": { - "fs-extra": "^10.1.0", - "ramda": "^0.28.0" - } - }, - "node_modules/file-system-cache/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-cache-dir/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-cache-dir/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-cache-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/find-cache-dir/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-cache-dir/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/find-cache-dir/node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/flush-write-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/flush-write-stream/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/flush-write-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/focus-lock": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.8.1.tgz", - "integrity": "sha512-/LFZOIo82WDsyyv7h7oc0MJF9ACOvDRdx9rWPZ2pgMfNWu/z8hQDBtOchuB/0BVLmuFOZjV02YwUVzNsWx/EzA==", - "dev": true, - "dependencies": { - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/focus-lock/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/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", - "integrity": "sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=10", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "eslint": ">= 6", - "typescript": ">= 2.7", - "vue-template-compiler": "*", - "webpack": ">= 4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/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/fork-ts-checker-webpack-plugin/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/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/fork-ts-checker-webpack-plugin/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/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/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/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "node_modules/from2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/from2/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/from2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/fs-extra": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", - "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", - "dev": true - }, - "node_modules/fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "node_modules/fs-write-stream-atomic/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/fs-write-stream-atomic/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/fs-write-stream-atomic/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "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==" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "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==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, - "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/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "dev": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, - "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/geometry-interfaces": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/geometry-interfaces/-/geometry-interfaces-1.1.4.tgz", - "integrity": "sha512-qD6OdkT6NcES9l4Xx3auTpwraQruU7dARbQPVO71MKvkGYw5/z/oIiGymuFXrRaEQa5Y67EIojUpaLeGEa5hGA==" - }, - "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-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.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.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/github-slugger": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", - "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==", - "dev": true - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "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": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-promise": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-4.2.2.tgz", - "integrity": "sha512-xcUzJ8NWN5bktoTIX7eOclO1Npxd/dyVqUJxlLIDasT4C7KZyqlPIwkdJ0Ypiy3p2ZKahTjK4M9uC3sNSfNMzw==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.3" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "individual", - "url": "https://github.com/sponsors/ahmadnassri" - }, - "peerDependencies": { - "glob": "^7.1.6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "dev": true, - "dependencies": { - "min-document": "^2.19.0", - "process": "^0.11.10" - } - }, - "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.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "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/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "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": "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/has-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-glob/-/has-glob-1.0.0.tgz", - "integrity": "sha512-D+8A457fBShSEI3tFCj65PAbT++5sKiFtdCdOam0gnfBgw9D277OERk+HM9qYJXmdVLZ/znez10SqHN0BBQ50g==", - "dev": true, - "dependencies": { - "is-glob": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-glob/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "license": "MIT", - "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, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/has-values/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-base/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/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hast-to-hyperscript": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", - "integrity": "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.3", - "comma-separated-tokens": "^1.0.0", - "property-information": "^5.3.0", - "space-separated-tokens": "^1.0.0", - "style-to-object": "^0.3.0", - "unist-util-is": "^4.0.0", - "web-namespaces": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz", - "integrity": "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==", - "dev": true, - "dependencies": { - "@types/parse5": "^5.0.0", - "hastscript": "^6.0.0", - "property-information": "^5.0.0", - "vfile": "^4.0.0", - "vfile-location": "^3.2.0", - "web-namespaces": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-parse-selector": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", - "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-raw": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz", - "integrity": "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==", - "dev": true, - "dependencies": { - "@types/hast": "^2.0.0", - "hast-util-from-parse5": "^6.0.0", - "hast-util-to-parse5": "^6.0.0", - "html-void-elements": "^1.0.0", - "parse5": "^6.0.0", - "unist-util-position": "^3.0.0", - "vfile": "^4.0.0", - "web-namespaces": "^1.0.0", - "xtend": "^4.0.0", - "zwitch": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-parse5": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz", - "integrity": "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==", - "dev": true, - "dependencies": { - "hast-to-hyperscript": "^9.0.0", - "property-information": "^5.0.0", - "web-namespaces": "^1.0.0", - "xtend": "^4.0.0", - "zwitch": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hastscript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", - "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", - "dev": true, - "dependencies": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dev": true, - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "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/html-encoding-sniffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", - "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-encoding": "^3.1.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/html-entities": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", - "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==", - "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/html-minifier-terser": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", - "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.1", - "clean-css": "^4.2.3", - "commander": "^4.1.1", - "he": "^1.2.0", - "param-case": "^3.0.3", - "relateurl": "^0.2.7", - "terser": "^4.6.3" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/html-minifier-terser/node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/html-minifier-terser/node_modules/terser": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", - "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", - "dev": true, - "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/html-minifier-terser/node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/html-void-elements": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", - "integrity": "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/html-webpack-plugin": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz", - "integrity": "sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A==", - "dev": true, - "dependencies": { - "@types/html-minifier-terser": "^5.0.0", - "@types/tapable": "^1.0.5", - "@types/webpack": "^4.41.8", - "html-minifier-terser": "^5.0.1", - "loader-utils": "^1.2.3", - "lodash": "^4.17.20", - "pretty-error": "^2.1.1", - "tapable": "^1.1.3", - "util.promisify": "1.0.0" - }, - "engines": { - "node": ">=6.9" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/html-webpack-plugin/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/html-webpack-plugin/node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/htmlparser2-svelte": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2-svelte/-/htmlparser2-svelte-4.1.0.tgz", - "integrity": "sha512-+4f4RBFz7Rj2Hp0ZbFbXC+Kzbd6S9PgjiuFtdT76VMNgKogrEZy0pG2UrPycPbrZzVEIM5lAT3lAdkSTCHLPjg==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^3.0.0", - "domutils": "^2.0.0", - "entities": "^2.0.0" - } - }, - "node_modules/htmlparser2-svelte/node_modules/domhandler": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz", - "integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", - "dev": true - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dependencies": { - "ms": "^2.0.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/icss-utils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", - "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", - "dev": true, - "dependencies": { - "postcss": "^7.0.14" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/icss-utils/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/icss-utils/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "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/iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==", - "dev": true - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/immutable": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", - "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", - "dev": true - }, - "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/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" - }, - "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==", - "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==" - }, - "node_modules/inline-style-parser": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", - "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", - "dev": true - }, - "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-absolute-url": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", - "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", - "dev": true, - "dependencies": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "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-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-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==", - "dev": true, - "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-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, - "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-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-dom": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-dom/-/is-dom-1.1.0.tgz", - "integrity": "sha512-u82f6mvhYxRPKpw8V1N0W8ce1xXwOrQtgGcxl6UCL5zBmZu3is/18K0rR7uFCnMDuAsS/3W54mGL4vsaFUQlEQ==", - "dev": true, - "dependencies": { - "is-object": "^1.0.1", - "is-window": "^1.0.2" - } - }, - "node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/is-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", - "dev": true - }, - "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==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==" - }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "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==", - "dev": true, - "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-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true, - "license": "MIT" - }, - "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.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "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-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "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-whitespace-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", - "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-window": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-window/-/is-window-1.0.2.tgz", - "integrity": "sha512-uj00kdXyZb9t9RcAUAwMZAnkBUwdYGhYlt7djMXhfyhUCzwNba50tIiBKR7q0l7tdoBtFVw/3JmLY6fI3rmZmg==", - "dev": true - }, - "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/is-word-character": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", - "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isomorphic-unfetch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz", - "integrity": "sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==", - "dev": true, - "dependencies": { - "node-fetch": "^2.6.1", - "unfetch": "^4.2.0" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "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/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/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/istanbul-lib-report/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/istanbul-lib-report/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/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/iterate-iterator": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", - "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/iterate-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", - "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", - "dev": true, - "dependencies": { - "es-get-iterator": "^1.0.2", - "iterate-iterator": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/jest-haste-map": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz", - "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "@types/graceful-fs": "^4.1.2", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-regex-util": "^26.0.0", - "jest-serializer": "^26.6.2", - "jest-util": "^26.6.2", - "jest-worker": "^26.6.2", - "micromatch": "^4.0.2", - "sane": "^4.0.3", - "walker": "^1.0.7" - }, - "engines": { - "node": ">= 10.14.2" - }, - "optionalDependencies": { - "fsevents": "^2.1.2" - } - }, - "node_modules/jest-mock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", - "dev": true, - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-mock/node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-mock/node_modules/@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/jest-mock/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-mock/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/jest-mock/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-mock/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-mock/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/jest-mock/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/jest-regex-util": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", - "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==", - "dev": true, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-serializer": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz", - "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==", - "dev": true, - "dependencies": { - "@types/node": "*", - "graceful-fs": "^4.2.4" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-util": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz", - "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "@types/node": "*", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "is-ci": "^2.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-util/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/jest-util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-util/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/jest-util/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/jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/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/jest-worker/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/js-string-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", - "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/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/jsdom": { - "version": "24.1.3", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.3.tgz", - "integrity": "sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssstyle": "^4.0.1", - "data-urls": "^5.0.0", - "decimal.js": "^10.4.3", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.5", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.12", - "parse5": "^7.1.2", - "rrweb-cssom": "^0.7.1", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.4", - "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^3.1.1", - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0", - "ws": "^8.18.0", - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "canvas": "^2.11.2" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom/node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/jsdom/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/jsdom/node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", - "dev": true, - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/jsdom/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/jsdom/node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/jsdom/node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/jsdom/node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/jsdom/node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/jsdom/node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "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-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "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": "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/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/json-to-html": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/json-to-html/-/json-to-html-0.1.2.tgz", - "integrity": "sha512-gwezGNdnxPnp+7m5aVFq080KGjURyLqLAMmoRlkfnapQYluxQX18Hu+MOPYOtPaipYSB1bawQem5cmvRo/aAMA==" - }, - "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "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/junk": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz", - "integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "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": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/klona": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", - "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/lazy-universal-dotenv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz", - "integrity": "sha512-prXSYk799h3GY3iOWnC6ZigYzMPjxN2svgjJ9shk7oMadSNX3wXy0B6F32PMJv7qtMnrIbUxoEHzbutvxR2LBQ==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.5.0", - "app-root-dir": "^1.0.2", - "core-js": "^3.0.4", - "dotenv": "^8.0.0", - "dotenv-expand": "^5.1.0" - }, - "engines": { - "node": ">=6.0.0", - "npm": ">=6.0.0", - "yarn": ">=1.0.0" - } - }, - "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/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==", - "dev": true - }, - "node_modules/loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", - "dev": true, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, - "node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.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.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.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.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/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==", - "dev": true, - "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==", - "dependencies": { - "tslib": "^2.0.3" - } - }, - "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==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/lz-string": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", - "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==", - "dev": true, - "bin": { - "lz-string": "bin/bin.js" - } - }, - "node_modules/magic-string": { - "version": "0.26.4", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.4.tgz", - "integrity": "sha512-e5uXtVJ22aEpK9u1+eQf0fSxHeqwyV19K+uGnlROCxUhzwRip9tBsaMViK/0vC3viyPd5Gtucp3UmEp/Q2cPTQ==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.8" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/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/make-fetch-happen/node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", - "engines": { - "node": ">=12" - } - }, - "node_modules/make-fetch-happen/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-fetch-happen/node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-fetch-happen/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-fetch-happen/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==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-fetch-happen/node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "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-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-or-similar": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", - "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", - "dev": true - }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/markdown-escapes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", - "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/mdast-squeeze-paragraphs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz", - "integrity": "sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==", - "dev": true, - "dependencies": { - "unist-util-remove": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-definitions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", - "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", - "dev": true, - "dependencies": { - "unist-util-visit": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz", - "integrity": "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==", - "dev": true, - "dependencies": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "mdast-util-definitions": "^4.0.0", - "mdurl": "^1.0.0", - "unist-builder": "^2.0.0", - "unist-util-generated": "^1.0.0", - "unist-util-position": "^3.0.0", - "unist-util-visit": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", - "integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", - "dev": true - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz", - "integrity": "sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw==", - "dev": true, - "dependencies": { - "fs-monkey": "^1.0.3" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/memoizerific": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", - "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", - "dev": true, - "dependencies": { - "map-or-similar": "^1.5.0" - } - }, - "node_modules/memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==", - "dev": true, - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "node_modules/memory-fs/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/memory-fs/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/memory-fs/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/meow": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.3.0.tgz", - "integrity": "sha512-vq4EJU5gIPN/DSDmPxZrGLUnrSJdwr7ZZ/DUALp787PgAfxZM2ogfzm1WvfKD02tMgyVwKgpnOBkREeSHs9BKA==", - "dev": true, - "optional": true, - "dependencies": { - "camelcase-keys": "^1.0.0", - "indent-string": "^1.1.0", - "minimist": "^1.1.0", - "object-assign": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/meow/node_modules/indent-string": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-1.2.2.tgz", - "integrity": "sha512-Z1vqf6lDC3f4N2mWqRywY6odjRatPNGDZgUr4DY9MLC14+Fp2/y+CI/RnNGlb8hD6ckscE/8DlZUwHUaiDBshg==", - "dev": true, - "optional": true, - "dependencies": { - "get-stdin": "^4.0.1", - "minimist": "^1.1.0", - "repeating": "^1.1.0" - }, - "bin": { - "indent-string": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/meow/node_modules/object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/microbuffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/microbuffer/-/microbuffer-1.0.0.tgz", - "integrity": "sha512-O/SUXauVN4x6RaEJFqSPcXNtLFL+QzJHKZlyDVYFwcDDRVca3Fa/37QXXC+4zAGGa4YhHrHxKXuuHvLDIQECtA==" - }, - "node_modules/microevent.ts": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", - "integrity": "sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g==", - "dev": true - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "bin": { - "miller-rabin": "bin/miller-rabin" - } - }, - "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.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/min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", - "dev": true, - "dependencies": { - "dom-walk": "^0.1.0" - } - }, - "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/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "node_modules/minipass": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", - "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "dependencies": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==", - "dev": true, - "dependencies": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "node_modules/move-concurrently/node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "node_modules/move-concurrently/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/move-concurrently/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/nan": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", - "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==" - }, - "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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/neatequal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/neatequal/-/neatequal-1.0.0.tgz", - "integrity": "sha512-sVt5awO4a4w24QmAthdrCPiVRW3naB8FGLdyadin01BH+6BzNPEBwGrpwCczQvPlULS6uXTItTe1PJ5P0kYm7A==", - "dependencies": { - "varstream": "^0.3.2" - } - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "node_modules/nested-error-stacks": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz", - "integrity": "sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==", - "dev": true - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-dir": { - "version": "0.1.17", - "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", - "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", - "dev": true, - "dependencies": { - "minimatch": "^3.0.2" - }, - "engines": { - "node": ">= 0.10.5" - } - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-gyp": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.1.0.tgz", - "integrity": "sha512-HkmN0ZpQJU7FLbJauJTHkHlSVAXlNGDAzH/VYFZGDOnFyn/Na3GlNJfkudmufOdS6/jNFhy88ObzL7ERz9es1g==", - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^12.22 || ^14.13 || >=16" - } - }, - "node_modules/node-gyp/node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/node-gyp/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "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-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dev": true, - "dependencies": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - } - }, - "node_modules/node-libs-browser/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/node-libs-browser/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - }, - "node_modules/node-libs-browser/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/node-libs-browser/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "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/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.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-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "dev": true, - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==", - "dev": true - }, - "node_modules/nwsapi": { - "version": "2.2.23", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", - "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==", - "dev": true, - "license": "MIT" - }, - "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==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/object-copy/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", - "dev": true, - "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-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "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.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.5.tgz", - "integrity": "sha512-yDNzckpM6ntyQiGTik1fKV1DcVDRS+w8bvpWNCBanvH5LfRX9O8WTHqQzG4RZwRAM4I0oU7TV11Lj5v0g20ibw==", - "dev": true, - "dependencies": { - "array.prototype.reduce": "^1.0.5", - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "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/open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", - "dev": true, - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "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.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", - "dev": true - }, - "node_modules/os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-all": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-all/-/p-all-2.1.0.tgz", - "integrity": "sha512-HbZxz5FONzz/z2gJfk6bFca0BCiSRF8jU3yCsWOen/vR6lZjfPOu/e7L3uFzTW1i0H8TlC3vqQstEJPQL4/uLA==", - "dev": true, - "dependencies": { - "p-map": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-all/node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-event": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", - "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", - "dev": true, - "dependencies": { - "p-timeout": "^3.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-filter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", - "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", - "dev": true, - "dependencies": { - "p-map": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-filter/node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-timeout": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", - "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", - "dev": true, - "dependencies": { - "p-finally": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "node_modules/parallel-transform": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", - "dev": true, - "dependencies": { - "cyclist": "^1.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "node_modules/parallel-transform/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/parallel-transform/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/parallel-transform/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "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-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/parse-entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", - "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", - "dev": true, - "dependencies": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "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/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true - }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", - "dev": true - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "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==", - "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==", - "dev": true, - "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==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dev": true, - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dev": true, - "dependencies": { - "find-up": "^5.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/pnp-webpack-plugin": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", - "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==", - "dev": true, - "dependencies": { - "ts-pnp": "^1.1.6" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/polished": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", - "integrity": "sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.17.8" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/polished/node_modules/@babel/runtime": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz", - "integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss": { - "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-flexbugs-fixes": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz", - "integrity": "sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ==", - "dev": true, - "dependencies": { - "postcss": "^7.0.26" - } - }, - "node_modules/postcss-flexbugs-fixes/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/postcss-flexbugs-fixes/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/postcss-loader": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", - "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", - "dev": true, - "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.4", - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0", - "semver": "^7.3.4" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/postcss-loader/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/postcss-loader/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", - "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", - "dev": true, - "dependencies": { - "postcss": "^7.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/postcss-modules-extract-imports/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/postcss-modules-extract-imports/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", - "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", - "dev": true, - "dependencies": { - "icss-utils": "^4.1.1", - "postcss": "^7.0.32", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/postcss-modules-local-by-default/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/postcss-modules-local-by-default/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/postcss-modules-scope": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", - "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", - "dev": true, - "dependencies": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/postcss-modules-scope/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/postcss-modules-scope/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/postcss-modules-values": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", - "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", - "dev": true, - "dependencies": { - "icss-utils": "^4.0.0", - "postcss": "^7.0.6" - } - }, - "node_modules/postcss-modules-values/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/postcss-modules-values/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.11", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", - "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", - "dev": true, - "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==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", - "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/pretty-error": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", - "integrity": "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^2.0.4" - } - }, - "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/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/promise.allsettled": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.6.tgz", - "integrity": "sha512-22wJUOD3zswWFqgwjNHa1965LvqTX87WPu/lreY2KSd7SVcERfuZ4GfUaOnJNnvtoIv2yXT/W00YIGMetXtFXg==", - "dev": true, - "dependencies": { - "array.prototype.map": "^1.0.5", - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "iterate-value": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/promise.prototype.finally": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.4.tgz", - "integrity": "sha512-nNc3YbgMfLzqtqvO/q5DP6RR0SiHI9pUPGzyDf1q+usTwCN2kjvAnJkBb7bHe3o+fFSBPpsGMoYtaSi+LTNqng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/prompts/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/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "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==", - "dev": true - }, - "node_modules/property-information": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", - "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", - "dev": true, - "dependencies": { - "xtend": "^4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true - }, - "node_modules/psl": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", - "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "funding": { - "url": "https://github.com/sponsors/lupomontero" - } - }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "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==", - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", - "dev": true, - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "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/ramda": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.28.0.tgz", - "integrity": "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-loader": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", - "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", - "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/raw-loader/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/react": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", - "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", - "dev": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-docgen": { - "version": "6.0.0-alpha.3", - "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-6.0.0-alpha.3.tgz", - "integrity": "sha512-DDLvB5EV9As1/zoUsct6Iz2Cupw9FObEGD3DMcIs3EDFIoSKyz8FZtoWj3Wj+oodrU4/NfidN0BL5yrapIcTSA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.7.5", - "@babel/generator": "^7.12.11", - "ast-types": "^0.14.2", - "commander": "^2.19.0", - "doctrine": "^3.0.0", - "estree-to-babel": "^3.1.0", - "neo-async": "^2.6.1", - "node-dir": "^0.1.10", - "resolve": "^1.17.0", - "strip-indent": "^3.0.0" - }, - "bin": { - "react-docgen": "bin/react-docgen.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/react-docgen-typescript": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", - "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", - "dev": true, - "peerDependencies": { - "typescript": ">= 4.3.x" - } - }, - "node_modules/react-docgen/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", - "dev": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - }, - "peerDependencies": { - "react": "^16.14.0" - } - }, - "node_modules/react-inspector": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-5.1.1.tgz", - "integrity": "sha512-GURDaYzoLbW8pMGXwYPDBIv6nqei4kK7LPRZ9q9HCZF54wqXz/dnylBp/kfE9XmekBhHvLDdcYeyIwSrvtOiWg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.0.0", - "is-dom": "^1.0.0", - "prop-types": "^15.0.0" - }, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0" - } - }, - "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-merge-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/react-merge-refs/-/react-merge-refs-1.1.0.tgz", - "integrity": "sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/react-refresh": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", - "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==", - "dev": true, - "engines": { - "node": ">=0.10.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/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.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "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==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", - "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regenerator-transform/node_modules/@babel/runtime": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz", - "integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/regexpu-core": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.1.tgz", - "integrity": "sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsgen": "^0.7.1", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsgen": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz", - "integrity": "sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==", - "dev": true - }, - "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/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/remark-external-links": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/remark-external-links/-/remark-external-links-8.0.0.tgz", - "integrity": "sha512-5vPSX0kHoSsqtdftSHhIYofVINC8qmp0nctkeU9YoJwV3YfiBRiI6cbFRJ0oI/1F9xS+bopXG0m2KS8VFscuKA==", - "dev": true, - "dependencies": { - "extend": "^3.0.0", - "is-absolute-url": "^3.0.0", - "mdast-util-definitions": "^4.0.0", - "space-separated-tokens": "^1.0.0", - "unist-util-visit": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-footnotes": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz", - "integrity": "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-mdx": { - "version": "1.6.22", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz", - "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==", - "dev": true, - "dependencies": { - "@babel/core": "7.12.9", - "@babel/helper-plugin-utils": "7.10.4", - "@babel/plugin-proposal-object-rest-spread": "7.12.1", - "@babel/plugin-syntax-jsx": "7.12.1", - "@mdx-js/util": "1.6.22", - "is-alphabetical": "1.0.4", - "remark-parse": "8.0.3", - "unified": "9.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-mdx/node_modules/@babel/core": { - "version": "7.12.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", - "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.5", - "@babel/helper-module-transforms": "^7.12.1", - "@babel/helpers": "^7.12.5", - "@babel/parser": "^7.12.7", - "@babel/template": "^7.12.7", - "@babel/traverse": "^7.12.9", - "@babel/types": "^7.12.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/remark-mdx/node_modules/@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", - "dev": true - }, - "node_modules/remark-mdx/node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", - "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-transform-parameters": "^7.12.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/remark-mdx/node_modules/@babel/plugin-syntax-jsx": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", - "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/remark-mdx/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/remark-mdx/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/remark-parse": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", - "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", - "dev": true, - "dependencies": { - "ccount": "^1.0.0", - "collapse-white-space": "^1.0.2", - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-whitespace-character": "^1.0.0", - "is-word-character": "^1.0.0", - "markdown-escapes": "^1.0.0", - "parse-entities": "^2.0.0", - "repeat-string": "^1.5.4", - "state-toggle": "^1.0.0", - "trim": "0.0.1", - "trim-trailing-lines": "^1.0.0", - "unherit": "^1.0.4", - "unist-util-remove-position": "^2.0.0", - "vfile-location": "^3.0.0", - "xtend": "^4.0.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-slug": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-6.1.0.tgz", - "integrity": "sha512-oGCxDF9deA8phWvxFuyr3oSJsdyUAxMFbA0mZ7Y1Sas+emILtO+e5WutF9564gDsEN4IXaQXm5pFo6MLH+YmwQ==", - "dev": true, - "dependencies": { - "github-slugger": "^1.0.0", - "mdast-util-to-string": "^1.0.0", - "unist-util-visit": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-squeeze-paragraphs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz", - "integrity": "sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw==", - "dev": true, - "dependencies": { - "mdast-squeeze-paragraphs": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "dev": true - }, - "node_modules/renderkid": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz", - "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^3.0.1" - } - }, - "node_modules/renderkid/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/renderkid/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/repeating": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-1.1.3.tgz", - "integrity": "sha512-Nh30JLeMHdoI+AsQ5eblhZ7YlTsM9wiJQe/AHIunlK3KWzvXhXb36IJ7K1IOeRjIOtzMjdUHjwXUFxKJoPTSOg==", - "dev": true, - "optional": true, - "dependencies": { - "is-finite": "^1.0.0" - }, - "bin": { - "repeating": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.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-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/rollup": { - "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/rrweb-cssom": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", - "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", - "dev": true, - "license": "MIT" - }, - "node_modules/rsvp": { - "version": "4.8.5", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", - "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", - "dev": true, - "engines": { - "node": "6.* || >= 7.*" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==", - "dev": true, - "dependencies": { - "aproba": "^1.1.1" - } - }, - "node_modules/run-queue/node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.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==", - "devOptional": true - }, - "node_modules/sane": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", - "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", - "deprecated": "some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added", - "dev": true, - "dependencies": { - "@cnakazawa/watch": "^1.0.3", - "anymatch": "^2.0.0", - "capture-exit": "^2.0.0", - "exec-sh": "^0.3.2", - "execa": "^1.0.0", - "fb-watchman": "^2.0.0", - "micromatch": "^3.1.4", - "minimist": "^1.1.1", - "walker": "~1.0.5" - }, - "bin": { - "sane": "src/cli.js" - }, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/sane/node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "node_modules/sane/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/sane/node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sane/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sane/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/sane/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/sane/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/sane/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/sane/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/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/sass": { - "version": "1.55.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.55.0.tgz", - "integrity": "sha512-Pk+PMy7OGLs9WaxZGJMn7S96dvlyVBwwtToX895WmCpAOr5YiJYEUJfiJidMuKb613z2xNWcXCHEuOvjZbqC6A==", - "dev": true, - "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "license": "ISC", - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, - "node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", - "dev": true, - "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-favicon": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz", - "integrity": "sha512-FMW2RvqNr03x+C0WxTyu6sOv21oOjkq5j8tjquWccwa6ScNyGFOGJVpuS1NmTVGBAHS07xnSKotgf2ehQmf9iA==", - "dev": true, - "dependencies": { - "etag": "~1.8.1", - "fresh": "0.5.2", - "ms": "2.1.1", - "parseurl": "~1.3.2", - "safe-buffer": "5.1.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-favicon/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "node_modules/serve-favicon/node_modules/safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "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==" - }, - "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": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/snapdragon/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz", + "integrity": "sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/snapdragon/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz", + "integrity": "sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dependencies": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "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==", - "engines": { - "node": ">=0.10.0" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz", + "integrity": "sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "deprecated": "See https://github.com/lydell/source-map-url#deprecated", - "dev": true - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "node_modules/space-separated-tokens": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz", + "integrity": "sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "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==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz", + "integrity": "sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", - "dev": true + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sveltejs/acorn-typescript": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.12.tgz", + "integrity": "sha512-J1jNYG23QWd67UfrQSFHtjhV37r9mVi0gdc12A3MWPldOjRK35Xk+um+qACPVjgw3AleiqoyEAhok8Wm3q46NA==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8.9.0" + } }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "node_modules/@sveltejs/vite-plugin-svelte": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-7.2.0.tgz", + "integrity": "sha512-1SpkuMSRLfugrVX+IrKfE1RUegzo8AQzKQ6qQPfVzbcWi5IhuTPaKb5ZrLpucleFznkc4/RTeSPoRnGWFxX+EQ==", "dev": true, + "license": "MIT", "dependencies": { - "extend-shallow": "^3.0.0" + "deepmerge": "^4.3.1", + "magic-string": "^0.30.21", + "obug": "^2.1.0", + "vitefu": "^1.1.2" }, "engines": { - "node": ">=0.10.0" + "node": "^20.19 || ^22.12 || >=24" + }, + "peerDependencies": { + "svelte": "^5.46.4", + "vite": "^8.0.0-beta.7 || ^8.0.0" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "node_modules/@tootallnate/once": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", + "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", "dev": true, - "dependencies": { - "minipass": "^3.1.1" - }, + "license": "MIT", "engines": { - "node": ">= 8" + "node": ">= 10" } }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", - "dev": true + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "license": "MIT" }, - "node_modules/state-toggle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", - "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", + "node_modules/@vusion/webfonts-generator": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@vusion/webfonts-generator/-/webfonts-generator-0.8.0.tgz", + "integrity": "sha512-1q17CF6umBEjlAtO37TzRw3aOCCAyFX+T4HPG70BmM6qx8s6H4/LQOa8eHFZq/oiMuMyd0FehKgUt/pqYlIMWA==", "dev": true, + "license": "Unlicense", "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" + "handlebars": "^4.0.11", + "mkdirp": "^1.0.4", + "q": "^1.1.2", + "svg2ttf": "^6.0.3", + "svgicons2svgfont": "^10.0.4", + "ttf2eot": "^3.0.0", + "ttf2woff": "^3.0.0", + "ttf2woff2": "^4.0.4", + "underscore": "^1.9.1", + "url-join": "^4.0.0" } }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "node_modules/@xmldom/xmldom": { + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz", + "integrity": "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==", "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=14.6" } }, - "node_modules/static-extend/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } + "license": "ISC" }, - "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.4.0" } }, - "node_modules/static-extend/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/static-extend/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, + "license": "MIT", "dependencies": { - "kind-of": "^3.0.2" + "debug": "4" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6.0.0" } }, - "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "dev": true, + "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5" + "humanize-ms": "^1.2.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 8.0.0" } }, - "node_modules/static-extend/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, + "license": "MIT", "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/static-extend/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "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==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, + "node_modules/ansi-to-html": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.7.2.tgz", + "integrity": "sha512-v6MqmEpNlxF+POuyhKkidusCHWWkaLcGRURzivcU3I9tv7k4JVhFcnukrM5Rlk2rUywdZuzYAZ+kbZqWCnfN3g==", + "license": "MIT", + "dependencies": { + "entities": "^2.2.0" + }, + "bin": { + "ansi-to-html": "bin/ansi-to-html" + }, "engines": { - "node": ">= 0.8" + "node": ">=8.0.0" } }, - "node_modules/store2": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/store2/-/store2-2.14.2.tgz", - "integrity": "sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w==", - "dev": true - }, - "node_modules/stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "node_modules/aproba": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", + "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", "dev": true, - "dependencies": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "node_modules/stream-browserify/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true + "license": "ISC" }, - "node_modules/stream-browserify/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", "dev": true, + "license": "ISC", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/stream-browserify/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "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, - "dependencies": { - "safe-buffer": "~5.1.0" - } + "license": "Python-2.0" }, - "node_modules/stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" + "node_modules/aria-query": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz", + "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" } }, - "node_modules/stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" + "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==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" } }, - "node_modules/stream-http/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/stream-http/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "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==", "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } + "license": "MIT" }, - "node_modules/stream-http/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", "dev": true, + "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "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==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string_decoder/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==", - "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/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" + "require-from-string": "^2.0.2" } }, - "node_modules/string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "file-uri-to-path": "1.0.0" } }, - "node_modules/string.prototype.padend": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz", - "integrity": "sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==", + "node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/string.prototype.padstart": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/string.prototype.padstart/-/string.prototype.padstart-3.1.4.tgz", - "integrity": "sha512-XqOHj8horGsF+zwxraBvMTkBFM28sS/jHBJajh17JtJKA92qazidiQbLosV4UA18azvLOVKYo/E3g3T9Y5826w==", + "node_modules/bufferstreams": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-3.0.0.tgz", + "integrity": "sha512-Qg0ggJUWJq90vtg4lDsGN9CDWvzBMQxhiEkSOD/sJfYt6BLect3eV1/S6K7SCSKJ34n60rf6U5eUPmQENVE4UA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "readable-stream": "^3.4.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8.12.0" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "dev": true, + "license": "ISC", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "balanced-match": "^1.0.0" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", "dependencies": { - "ansi-regex": "^5.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, + "license": "ISC", "engines": { - "node": ">=6" + "node": ">=12" } }, - "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==", + "node_modules/cacache/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, + "license": "ISC", "dependencies": { - "min-indent": "^1.0.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "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" + "node_modules/chart.js": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz", + "integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==", + "license": "MIT", + "dependencies": { + "@kurkle/color": "^0.3.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "pnpm": ">=8" } }, - "node_modules/style-loader": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", - "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", "dev": true, + "license": "MIT", "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^2.7.0" + "readdirp": "^5.0.0" }, "engines": { - "node": ">= 8.9.0" + "node": ">= 20.19.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/style-to-object": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", - "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==", - "dev": true, - "dependencies": { - "inline-style-parser": "0.1.1" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, + "license": "ISC", "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, - "node_modules/svelte": { - "version": "3.50.1", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.50.1.tgz", - "integrity": "sha512-bS4odcsdj5D5jEg6riZuMg5NKelzPtmsCbD9RG+8umU03TeNkdWnP6pqbCm0s8UQNBkqk29w/Bdubn3C+HWSwA==", + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", "engines": { - "node": ">= 8" + "node": ">=6" } }, - "node_modules/svelte-chartjs": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/svelte-chartjs/-/svelte-chartjs-3.1.2.tgz", - "integrity": "sha512-3+6gY2IJ9Ua8R9pk3iS1ypa7Z9OoXCJb9oPwIfTp7caJM+X+RrWnH2CTkGAq7FeSxc2nnmW08tYN88Q8Y+5M+w==", - "peerDependencies": { - "chart.js": "^3.5.0 || ^4.0.0", - "svelte": "^3.45.0" + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" } }, - "node_modules/svelte-hmr": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.0.tgz", - "integrity": "sha512-Aw21SsyoohyVn4yiKXWPNCSW2DQNH/76kvUnE9kpt4h9hcg9tfyQc6xshx9hzgMfGF0kVx0EGD8oBMWSnATeOg==", + "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, + "license": "MIT", "engines": { - "node": "^12.20 || ^14.13.1 || >= 16" - }, - "peerDependencies": { - "svelte": ">=3.19.0" + "node": ">= 10" } }, - "node_modules/svelte-intersection-observer": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/svelte-intersection-observer/-/svelte-intersection-observer-0.10.0.tgz", - "integrity": "sha512-GdOTMSrRpoBciMe+NbocsHOBvqKJ5OiL5H8Jz4mBoDGHba9VOI4oGeXAmMOmh8mi5gq95+0b0DVI+6alcQ7TCA==", - "dev": true - }, - "node_modules/svelte-loading-spinners": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/svelte-loading-spinners/-/svelte-loading-spinners-0.3.4.tgz", - "integrity": "sha512-vKaW71QMCBcTNijAGc0mUl8k3DQ66iYmp6MB8BMGCXyWk82bTrcLy8FOnSm9fE+8q6TwzD6PLUoYFHt0II93Xw==" + "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, + "license": "MIT" }, - "node_modules/svelte-routing": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/svelte-routing/-/svelte-routing-1.6.0.tgz", - "integrity": "sha512-+DbrSGttLA6lan7oWFz1MjyGabdn3tPRqn8Osyc471ut2UgCrzM5x1qViNMc2gahOP6fKbKK1aNtZMJEQP2vHQ==", - "dependencies": { - "svelte2tsx": "^0.1.157" - }, - "peerDependencies": { - "svelte": "^3.20.x" - } + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true, + "license": "ISC" }, - "node_modules/svelte2tsx": { - "version": "0.1.193", - "resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.1.193.tgz", - "integrity": "sha512-vzy4YQNYDnoqp2iZPnJy7kpPAY6y121L0HKrSBjU/IWW7DQ6T7RMJed2VVHFmVYm0zAGYMDl9urPc6R4DDUyhg==", - "dependencies": { - "dedent-js": "^1.0.1", - "pascal-case": "^3.1.1" - }, - "peerDependencies": { - "svelte": "^3.24", - "typescript": "^4.1.2" - } + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" }, - "node_modules/sveltedoc-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/sveltedoc-parser/-/sveltedoc-parser-4.2.1.tgz", - "integrity": "sha512-sWJRa4qOfRdSORSVw9GhfDEwsbsYsegnDzBevUCF6k/Eis/QqCu9lJ6I0+d/E2wOWCjOhlcJ3+jl/Iur+5mmCw==", + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", "dev": true, + "license": "MIT", "dependencies": { - "eslint": "8.4.1", - "espree": "9.2.0", - "htmlparser2-svelte": "4.1.0" + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" }, "engines": { - "node": ">=10.0.0" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, - "node_modules/svg-pathdata": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", - "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", - "engines": { - "node": ">=12.0.0" - } + "node_modules/cubic2quad": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/cubic2quad/-/cubic2quad-1.2.1.tgz", + "integrity": "sha512-wT5Y7mO8abrV16gnssKdmIhIbA9wSkeMzhh27jAguKrV82i24wER0vL5TGhUJ9dbJNDcigoRZ0IAHFEEEI4THQ==", + "dev": true, + "license": "MIT" }, - "node_modules/svg2ttf": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/svg2ttf/-/svg2ttf-6.0.3.tgz", - "integrity": "sha512-CgqMyZrbOPpc+WqH7aga4JWkDPso23EgypLsbQ6gN3uoPWwwiLjXvzgrwGADBExvCRJrWFzAeK1bSoSpE7ixSQ==", + "node_modules/data-urls": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", + "dev": true, + "license": "MIT", "dependencies": { - "@xmldom/xmldom": "^0.7.2", - "argparse": "^2.0.1", - "cubic2quad": "^1.2.1", - "lodash": "^4.17.10", - "microbuffer": "^1.0.0", - "svgpath": "^2.1.5" + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.0" }, - "bin": { - "svg2ttf": "svg2ttf.js" + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/svg2ttf/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==" - }, - "node_modules/svgicons2svgfont": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/svgicons2svgfont/-/svgicons2svgfont-10.0.6.tgz", - "integrity": "sha512-fUgQEVg3XwTbOHvlXahHGqCet5Wvfo1bV4DCvbSRvjsOCPCRunYbG4dUJCPegps37BMph3eOrfoobhH5AWuC6A==", + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz", + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", + "dev": true, + "license": "MIT", "dependencies": { - "commander": "^7.2.0", - "geometry-interfaces": "^1.1.4", - "glob": "^7.1.6", - "neatequal": "^1.0.0", - "readable-stream": "^3.4.0", - "sax": "^1.2.4", - "svg-pathdata": "^6.0.0" - }, - "bin": { - "svgicons2svgfont": "bin/svgicons2svgfont.js" + "@exodus/bytes": "^1.11.0", + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.1" }, "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/svgicons2svgfont/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==", - "engines": { - "node": ">= 10" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, - "node_modules/svgpath": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/svgpath/-/svgpath-2.5.0.tgz", - "integrity": "sha512-o/vohwqjUO9nDAh4rcjE3KaW/v//At8UJu2LJMybXidf5QLQLVA4bxH0//4YCsr+1H4Gw1Wi/Jc62ynzSBYidw==" - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true, - "license": "MIT" - }, - "node_modules/symbol.prototype.description": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/symbol.prototype.description/-/symbol.prototype.description-1.0.5.tgz", - "integrity": "sha512-x738iXRYsrAt9WBhRCVG5BtIC3B7CUkFwbHW2zOvGtwM33s7JjrCDyq8V0zgMYVb5ymsL8+qkzzpANH63CPQaQ==", + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-symbol-description": "^1.0.0", - "has-symbols": "^1.0.2", - "object.getownpropertydescriptors": "^2.1.2" + "ms": "^2.1.3" }, "engines": { - "node": ">= 0.11.15" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/synchronous-promise": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.16.tgz", - "integrity": "sha512-qImOD23aDfnIDNqlG1NOehdB9IYsn1V9oByPjKY1nakv2MQYCEMyX033/q+aEtYCpmYK1cv2+NTmlH+ra6GA5A==", - "dev": true + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" }, - "node_modules/table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "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, - "dependencies": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, - "node_modules/table/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/table/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "node_modules/devalue": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.9.0.tgz", + "integrity": "sha512-RWrqdArjvPbsATEhOPUo6Wndc/iWnkWKlhIrdlF3zMMYo/c3CVtoaVAyLtWxz5h8nSlkHzxnzV2uLydPXmtF+A==", + "license": "MIT" }, - "node_modules/table/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/table/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" + "iconv-lite": "^0.6.2" } }, - "node_modules/table/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "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, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/telejson": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/telejson/-/telejson-6.0.8.tgz", - "integrity": "sha512-nerNXi+j8NK1QEfBHtZUN/aLdDcyupA//9kAboYLrtzZlPLpUfqbVGWb9zz91f/mIjRbAYhbgtnJHY8I1b5MBg==", + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "dev": true, - "dependencies": { - "@types/is-function": "^1.0.0", - "global": "^4.4.0", - "is-function": "^1.0.2", - "is-regex": "^1.1.2", - "is-symbol": "^1.0.3", - "isobject": "^4.0.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3" - } + "license": "MIT" }, - "node_modules/telejson/node_modules/isobject": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", - "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">=0.10.0" - } + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/esm-env": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", + "license": "MIT" }, - "node_modules/terser": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.0.tgz", - "integrity": "sha512-KjTV81QKStSfwbNiwlBXfcgMcOloyuRdb62/iLFPGBcVNF4EXjhdYBhYHmbJpiBrVxZhDvltE11j+LBQUxEEJg==", - "dev": true, + "node_modules/esrap": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.3.2.tgz", + "integrity": "sha512-40GyiEJevYKXzYTHtZkFqAgTjLOuFcaXMao8TPyOlnWTlkHDlvZ6mPMJaJyOqVwrVCgomEG1WhJd81w0X+IcCw==", + "license": "MIT", "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" + "@jridgewell/sourcemap-codec": "^1.4.15" }, - "bin": { - "terser": "bin/terser" + "peerDependencies": { + "@typescript-eslint/types": "^8.2.0" }, - "engines": { - "node": ">=10" + "peerDependenciesMeta": { + "@typescript-eslint/types": { + "optional": true + } } }, - "node_modules/terser-webpack-plugin": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", - "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", "dev": true, - "dependencies": { - "cacache": "^15.0.5", - "find-cache-dir": "^3.3.1", - "jest-worker": "^26.5.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "source-map": "^0.6.1", - "terser": "^5.3.4", - "webpack-sources": "^1.4.3" - }, + "license": "Apache-2.0" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=12.0.0" }, "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/terser-webpack-plugin/node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } + "license": "MIT" }, - "node_modules/terser-webpack-plugin/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==", + "node_modules/fs-extra": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.4.0.tgz", + "integrity": "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==", "dev": true, + "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=14.14" } }, - "node_modules/terser-webpack-plugin/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==", + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, + "license": "ISC", "dependencies": { - "p-locate": "^4.1.0" + "minipass": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/terser-webpack-plugin/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "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, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "ISC" }, - "node_modules/terser-webpack-plugin/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==", + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=8" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/terser-webpack-plugin/node_modules/p-locate/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==", + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", "dev": true, + "license": "ISC", "dependencies": { - "p-try": "^2.0.0" + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/terser-webpack-plugin/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==", + "node_modules/geometry-interfaces": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/geometry-interfaces/-/geometry-interfaces-1.1.4.tgz", + "integrity": "sha512-qD6OdkT6NcES9l4Xx3auTpwraQruU7dARbQPVO71MKvkGYw5/z/oIiGymuFXrRaEQa5Y67EIojUpaLeGEa5hGA==", "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "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": ">= 10.13.0" + "node": "*" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "node_modules/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==", + "dev": true, + "license": "ISC" }, - "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==", + "node_modules/handlebars": { + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", "dev": true, + "license": "MIT", "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" }, "engines": { - "node": ">=8" - } - }, - "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/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" } }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } + "license": "ISC" }, - "node_modules/timers-browserify": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", - "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", "dev": true, + "license": "MIT", "dependencies": { - "setimmediate": "^1.0.4" + "@exodus/bytes": "^1.6.0" }, "engines": { - "node": ">=0.6.0" + "node": "^20.19.0 || ^22.12.0 || >=24.0.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-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==", - "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==", + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "dev": true, - "engines": { - "node": ">=4" - } + "license": "BSD-2-Clause" }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, + "license": "MIT", "dependencies": { - "kind-of": "^3.0.2" + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/to-object-path/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, + "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "dev": true, + "license": "MIT", "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" + "ms": "^2.0.0" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "is-number": "^7.0.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">=8.0" + "node": ">=0.10.0" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "node_modules/immutable": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.9.tgz", + "integrity": "sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==", "dev": true, - "engines": { - "node": ">=0.6" - } + "license": "MIT" }, - "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.8.19" } }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "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, "license": "MIT", "engines": { - "node": ">= 4.0.0" + "node": ">=8" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==", - "dev": true + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true, + "license": "ISC" }, - "node_modules/trim-trailing-lines": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", - "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", + "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, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/trough": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", - "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "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, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "license": "ISC" }, - "node_modules/ts-dedent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", - "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "node_modules/ip-address": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz", + "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6.10" + "node": ">= 12" } }, - "node_modules/ts-pnp": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", - "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", + "optional": true, "engines": { - "node": ">=6" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, - "node_modules/ttf2eot": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ttf2eot/-/ttf2eot-3.1.0.tgz", - "integrity": "sha512-aHTbcYosNHVqb2Qtt9Xfta77ae/5y0VfdwNLUS6sGBeGr22cX2JDMo/i5h3uuOf+FAD3akYOr17+fYd5NK8aXw==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "ttf2eot": "ttf2eot.js" + "node": ">=0.10.0" } }, - "node_modules/ttf2eot/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==" - }, - "node_modules/ttf2woff": { + "node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ttf2woff/-/ttf2woff-3.0.0.tgz", - "integrity": "sha512-OvmFcj70PhmAsVQKfC15XoKH55cRWuaRzvr2fpTNhTNer6JBpG8n6vOhRrIgxMjcikyYt88xqYXMMVapJ4Rjvg==", - "dependencies": { - "argparse": "^2.0.1", - "pako": "^1.0.0" - }, - "bin": { - "ttf2woff": "ttf2woff.js" - } - }, - "node_modules/ttf2woff/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==" - }, - "node_modules/ttf2woff2": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/ttf2woff2/-/ttf2woff2-4.0.5.tgz", - "integrity": "sha512-zpoU0NopfjoyVqkFeQ722SyKk/n607mm5OHxuDS/wCCSy82B8H3hHXrezftA2KMbKqfJIjie2lsJHdvPnBGbsw==", - "hasInstallScript": true, - "dependencies": { - "bindings": "^1.5.0", - "bufferstreams": "^3.0.0", - "nan": "^2.14.2", - "node-gyp": "^9.0.0" - }, - "bin": { - "ttf2woff2": "bin/ttf2woff2.js" - }, + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "prelude-ls": "^1.2.1" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=0.10.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "MIT" }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true, + "license": "MIT" + }, + "node_modules/is-reference": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", + "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", + "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" + "@types/estree": "^1.0.6" } }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "node_modules/jsdom": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-30.0.1.tgz", + "integrity": "sha512-52v7mUVUfNQVYYqE1lcdaymWL0njO7lTLUog6ZvW2U5KsbiLk/GnZlVJ+qx0xfNJZ6Gn+KSpPNE52vurbxZwrA==", "dev": true, + "license": "MIT", "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typescript": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", - "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "@asamuzakjp/css-color": "^6.0.5", + "@asamuzakjp/dom-selector": "^8.3.0", + "@bramus/specificity": "^2.4.2", + "@csstools/css-syntax-patches-for-csstree": "^1.1.7", + "@exodus/bytes": "^1.15.1", + "css-tree": "^3.2.1", + "data-urls": "^7.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.5.2", + "parse5": "^8.0.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.2", + "undici": "^8.9.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.1", + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^17.1.0", + "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uglify-js": { - "version": "3.17.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.2.tgz", - "integrity": "sha512-bbxglRjsGQMchfvXZNusUcYgiB9Hx2K4AHYXQy2DITZ9Rd+JzhX7+hoocE5Winr7z2oHvPsekkBwXtigvxevXg==", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "peerDependencies": { + "canvas": "^3.2.3" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "canvas": { + "optional": true + } } }, - "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" - }, - "node_modules/unfetch": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", - "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==", - "dev": true - }, - "node_modules/unherit": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", - "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", "dev": true, + "license": "MIT", "dependencies": { - "inherits": "^2.0.0", - "xtend": "^4.0.0" + "universalify": "^2.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, - "engines": { - "node": ">=4" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", "dev": true, + "license": "MPL-2.0", "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" + "detect-libc": "^2.0.3" }, "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", - "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", - "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==", + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=4" - } - }, - "node_modules/unified": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", - "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", - "dev": true, - "dependencies": { - "bail": "^1.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^2.0.0", - "trough": "^1.0.0", - "vfile": "^4.0.0" + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.10.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/union-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "dependencies": { - "unique-slug": "^2.0.0" - } - }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4" - } - }, - "node_modules/unist-builder": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz", - "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==", - "dev": true, + "node": ">= 12.0.0" + }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/unist-util-generated": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", - "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==", + "node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/unist-util-is": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", - "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/unist-util-position": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz", - "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==", + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/unist-util-remove": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz", - "integrity": "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==", + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "unist-util-is": "^4.0.0" + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/unist-util-remove-position": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz", - "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==", + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "unist-util-visit": "^2.0.0" + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/unist-util-stringify-position": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", - "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@types/unist": "^2.0.2" + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/unist-util-visit": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", - "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0", - "unist-util-visit-parents": "^3.0.0" + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/unist-util-visit-parents": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", - "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^4.0.0" + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/parcel" } }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "node_modules/locate-character": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "dev": true, - "engines": { - "node": ">= 10.0.0" - } + "license": "MIT" }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", "dev": true, + "license": "BlueOak-1.0.0", "engines": { - "node": ">= 0.8" + "node": "20 || >=22" } }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", - "dev": true, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", "dev": true, + "license": "ISC", "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, + "license": "ISC", "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "license": "CC0-1.0" }, - "node_modules/unset-value/node_modules/isarray": { + "node_modules/microbuffer": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true + "resolved": "https://registry.npmjs.org/microbuffer/-/microbuffer-1.0.0.tgz", + "integrity": "sha512-O/SUXauVN4x6RaEJFqSPcXNtLFL+QzJHKZlyDVYFwcDDRVca3Fa/37QXXC+4zAGGa4YhHrHxKXuuHvLDIQECtA==", + "dev": true, + "license": "MIT" }, - "node_modules/untildify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz", - "integrity": "sha512-sJjbDp2GodvkB0FZZcn7k6afVisqX5BZD7Yq3xp4nN2O15BBK0cLm3Vwn2vQaF7UDS0UUsrQMkkplmDI5fskig==", + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, - "optional": true, + "license": "ISC", "dependencies": { - "os-homedir": "^1.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, - "optional": true, - "engines": { - "node": ">=4", - "yarn": "*" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz", - "integrity": "sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==", + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], + "license": "ISC", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist-lint": "cli.js" + "yallist": "^4.0.0" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "engines": { + "node": ">=8" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "dev": true, + "license": "ISC", "dependencies": { - "punycode": "^2.1.0" + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, - "node_modules/url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", + "node_modules/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "dev": true, + "license": "MIT", "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" } }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" - }, - "node_modules/url-loader": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", - "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "node_modules/minipass-flush": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", + "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "loader-utils": "^2.0.0", - "mime-types": "^2.1.27", - "schema-utils": "^3.0.0" + "minipass": "^3.0.0" }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" }, - "peerDependencies": { - "file-loader": "*", - "webpack": "^4.0.0 || ^5.0.0" + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" }, - "peerDependenciesMeta": { - "file-loader": { - "optional": true - } + "engines": { + "node": ">=8" } }, - "node_modules/url-loader/node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" + "minipass": "^3.0.0", + "yallist": "^4.0.0" }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">= 8" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "license": "MIT", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", - "dev": true + "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, + "license": "MIT" }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "node_modules/nan": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.28.0.tgz", + "integrity": "sha512-fTsDz99OTq2sVePhGdp4qQhggZFtKr64ZNVyVajRKtMOkJxYekplBh577PiJB12v/D3s2E5cGtOI45LWp6rnLQ==", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "node_modules/nanoid": { + "version": "3.3.17", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz", + "integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==", "dev": true, - "dependencies": { - "inherits": "2.0.3" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "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/util.promisify": { + "node_modules/neatequal": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "resolved": "https://registry.npmjs.org/neatequal/-/neatequal-1.0.0.tgz", + "integrity": "sha512-sVt5awO4a4w24QmAthdrCPiVRW3naB8FGLdyadin01BH+6BzNPEBwGrpwCczQvPlULS6uXTItTe1PJ5P0kYm7A==", "dev": true, + "license": "MIT", "dependencies": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" + "varstream": "^0.3.2" } }, - "node_modules/util/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4.0" + "node": ">= 0.6" } }, - "node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/uuid-browser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid-browser/-/uuid-browser-3.1.0.tgz", - "integrity": "sha512-dsNgbLaTrd6l3MMxTtouOCFw4CBFc/3a+GgYA2YyrJvyQ1u6q4pcu3ktLoUZ/VN/Aw9WsauazbgsgdfVWgAKQg==", - "dev": true + "license": "MIT" }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true }, - "node_modules/v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "node_modules/node-gyp": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", + "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": ">=10.12.0" + "node": "^12.13 || ^14.13 || >=16" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", "dev": true, + "license": "ISC", "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/varstream": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/varstream/-/varstream-0.3.2.tgz", - "integrity": "sha512-OpR3Usr9dGZZbDttlTxdviGdxiURI0prX68+DuaN/JfIDbK9ZOmREKM6PgmelsejMnhgjXmEEEgf+E4NbsSqMg==", - "dependencies": { - "readable-stream": "^1.0.33" + "abbrev": "^1.0.0" }, "bin": { - "json2varstream": "cli/json2varstream.js", - "varstream2json": "cli/varstream2json.js" + "nopt": "bin/nopt.js" }, "engines": { - "node": ">=0.10.*" - } - }, - "node_modules/varstream/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "node_modules/varstream/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/varstream/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "engines": { - "node": ">= 0.8" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/vfile": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", - "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", "dev": true, + "license": "ISC", "dependencies": { - "@types/unist": "^2.0.0", - "is-buffer": "^2.0.0", - "unist-util-stringify-position": "^2.0.0", - "vfile-message": "^2.0.0" + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/vfile-location": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz", - "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==", + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" } }, - "node_modules/vfile-message": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", - "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "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, + "license": "ISC", "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "wrappy": "1" } }, - "node_modules/vite": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.4.tgz", - "integrity": "sha512-JoQI08aBjY9lycL7jcEq4p9o1xUjq5aRvdH4KWaXtkSx7e7RpAh9D3IjzDWRD4Fg44LS3oDAIOG/Kq1L+82psA==", + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, + "license": "MIT", "dependencies": { - "esbuild": "^0.15.6", - "postcss": "^8.4.16", - "resolve": "^1.22.1", - "rollup": "~2.78.0" - }, - "bin": { - "vite": "bin/vite.js" + "aggregate-error": "^3.0.0" }, "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "less": "*", - "sass": "*", - "stylus": "*", - "terser": "^5.4.0" + "node": ">=10" }, - "peerDependenciesMeta": { - "less": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "terser": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", - "dev": true + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" }, - "node_modules/w3c-xmlserializer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "node_modules/parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", "dev": true, "license": "MIT", "dependencies": { - "xml-name-validator": "^5.0.0" + "entities": "^8.0.0" }, - "engines": { - "node": ">=18" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "node_modules/parse5/node_modules/entities": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", "dev": true, - "dependencies": { - "makeerror": "1.0.12" + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "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, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, + "license": "MIT", "engines": { - "node": ">=10.13.0" + "node": ">=0.10.0" } }, - "node_modules/watchpack-chokidar2": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", - "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, - "optional": true, - "dependencies": { - "chokidar": "^2.1.8" - } + "license": "ISC" }, - "node_modules/watchpack-chokidar2/node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, - "optional": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/watchpack-chokidar2/node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", "dev": true, - "optional": 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" + } + ], + "license": "MIT", "dependencies": { - "remove-trailing-separator": "^1.0.1" + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || >=14" } }, - "node_modules/watchpack-chokidar2/node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } + "license": "ISC" }, - "node_modules/watchpack-chokidar2/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, - "optional": true, + "license": "MIT", "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "err-code": "^2.0.2", + "retry": "^0.12.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/watchpack-chokidar2/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "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, - "optional": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/watchpack-chokidar2/node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "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, - "optional": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" + "license": "MIT", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" } }, - "node_modules/watchpack-chokidar2/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "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, - "optional": true, + "license": "MIT", "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/watchpack-chokidar2/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "node_modules/readdirp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz", + "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==", "dev": true, - "optional": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/watchpack-chokidar2/node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "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, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - }, + "license": "MIT", "engines": { - "node": ">= 4.0" + "node": ">=0.10.0" } }, - "node_modules/watchpack-chokidar2/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, - "optional": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "license": "MIT", + "engines": { + "node": ">= 4" } }, - "node_modules/watchpack-chokidar2/node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "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, - "optional": true, + "license": "ISC", "dependencies": { - "is-extglob": "^2.1.0" + "glob": "^7.1.3" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/watchpack-chokidar2/node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "node_modules/rolldown": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.3.tgz", + "integrity": "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==", "dev": true, - "optional": true, + "license": "MIT", "dependencies": { - "binary-extensions": "^1.0.0" + "@oxc-project/types": "=0.143.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" }, "engines": { - "node": ">=0.10.0" + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.2.3", + "@rolldown/binding-darwin-arm64": "1.2.3", + "@rolldown/binding-darwin-x64": "1.2.3", + "@rolldown/binding-freebsd-x64": "1.2.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.3", + "@rolldown/binding-linux-arm64-gnu": "1.2.3", + "@rolldown/binding-linux-arm64-musl": "1.2.3", + "@rolldown/binding-linux-ppc64-gnu": "1.2.3", + "@rolldown/binding-linux-s390x-gnu": "1.2.3", + "@rolldown/binding-linux-x64-gnu": "1.2.3", + "@rolldown/binding-linux-x64-musl": "1.2.3", + "@rolldown/binding-openharmony-arm64": "1.2.3", + "@rolldown/binding-win32-arm64-msvc": "1.2.3", + "@rolldown/binding-win32-x64-msvc": "1.2.3" } }, - "node_modules/watchpack-chokidar2/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "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" + } + ], + "license": "MIT" + }, + "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, + "license": "MIT", "optional": true }, - "node_modules/watchpack-chokidar2/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "node_modules/sass": { + "version": "1.102.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.102.0.tgz", + "integrity": "sha512-NSOyTnaQF7rTAEOtI2fwb386vL+akyiQLBZu8Na7hXCb+umJy0GAqlcMIaqACZ6Z1VgTBS4K9PG6B3IdjHGJsw==", "dev": true, - "optional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^5.0.0", + "immutable": "^5.1.5", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, "engines": { - "node": ">=0.10.0" + "node": ">=20.19.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" } }, - "node_modules/watchpack-chokidar2/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", "dev": true, - "optional": true, - "dependencies": { - "kind-of": "^3.0.2" - }, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=0.10.0" + "node": ">=11.0.0" } }, - "node_modules/watchpack-chokidar2/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, - "optional": true, + "license": "ISC", "dependencies": { - "is-buffer": "^1.1.5" + "xmlchars": "^2.2.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=v12.22.7" } }, - "node_modules/watchpack-chokidar2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "optional": true - }, - "node_modules/watchpack-chokidar2/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "dev": true, - "optional": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/watchpack-chokidar2/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true, - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } + "license": "ISC" }, - "node_modules/watchpack-chokidar2/node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "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, - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } + "license": "ISC" }, - "node_modules/watchpack-chokidar2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/watchpack-chokidar2/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "node_modules/socks": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", + "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==", "dev": true, - "optional": true, + "license": "MIT", "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/web-namespaces": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", - "integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "node": ">= 10.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/webpack": { - "version": "4.46.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", - "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", "dev": true, + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/wasm-edit": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "acorn": "^6.4.1", - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^4.5.0", - "eslint-scope": "^4.0.3", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.4.0", - "loader-utils": "^1.2.3", - "memory-fs": "^0.4.1", - "micromatch": "^3.1.10", - "mkdirp": "^0.5.3", - "neo-async": "^2.6.1", - "node-libs-browser": "^2.2.1", - "schema-utils": "^1.0.0", - "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.3", - "watchpack": "^1.7.4", - "webpack-sources": "^1.4.1" - }, - "bin": { - "webpack": "bin/webpack.js" + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" }, "engines": { - "node": ">=6.11.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - }, - "webpack-command": { - "optional": true - } + "node": ">= 10" } }, - "node_modules/webpack-dev-middleware": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", - "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "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, - "dependencies": { - "memory-fs": "^0.4.1", - "mime": "^2.4.4", - "mkdirp": "^0.5.1", - "range-parser": "^1.2.1", - "webpack-log": "^2.0.0" - }, + "license": "BSD-3-Clause", "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "node": ">=0.10.0" } }, - "node_modules/webpack-dev-middleware/node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "node_modules/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==", "dev": true, - "bin": { - "mime": "cli.js" - }, + "license": "BSD-3-Clause", "engines": { - "node": ">=4.0.0" + "node": ">=0.10.0" } }, - "node_modules/webpack-dev-middleware/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", "dev": true, + "license": "ISC", "dependencies": { - "minimist": "^1.2.6" + "minipass": "^3.1.1" }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/webpack-filter-warnings-plugin": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/webpack-filter-warnings-plugin/-/webpack-filter-warnings-plugin-1.2.1.tgz", - "integrity": "sha512-Ez6ytc9IseDMLPo0qCuNNYzgtUl8NovOqjIq4uAU8LTD4uoa1w1KpZyyzFtLTEMZpkkOkLfL9eN+KGYdk1Qtwg==", - "dev": true, "engines": { - "node": ">= 4.3 < 5.0.0 || >= 5.10" - }, - "peerDependencies": { - "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/webpack-hot-middleware": { - "version": "2.25.3", - "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.25.3.tgz", - "integrity": "sha512-IK/0WAHs7MTu1tzLTjio73LjS3Ov+VvBKQmE8WPlJutgG5zT6Urgq/BbAdRrHTRpyzK0dvAvFh1Qg98akxgZpA==", + "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, + "license": "MIT", "dependencies": { - "ansi-html-community": "0.0.8", - "html-entities": "^2.1.0", - "strip-ansi": "^6.0.0" + "safe-buffer": "~5.2.0" } }, - "node_modules/webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/webpack-log/node_modules/ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, + "node_modules/svelte": { + "version": "5.56.8", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.56.8.tgz", + "integrity": "sha512-PY8LOw7xP6c8IOiVqdo0sbbZVYhXRSfklOQLAUyGBKqjTX0wx/z4l/9J+PmBpmlLnxzEb1NqltxQ5/wZme/Cmg==", + "license": "MIT", "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" + "@jridgewell/remapping": "^2.3.4", + "@jridgewell/sourcemap-codec": "^1.5.0", + "@sveltejs/acorn-typescript": "^1.0.10", + "@types/estree": "^1.0.5", + "@types/trusted-types": "^2.0.7", + "acorn": "^8.12.1", + "aria-query": "5.3.1", + "axobject-query": "^4.1.0", + "clsx": "^2.1.1", + "devalue": "^5.8.1", + "esm-env": "^1.2.1", + "esrap": "^2.2.12", + "is-reference": "^3.0.3", + "locate-character": "^3.0.0", + "magic-string": "^0.30.11", + "zimmerframe": "^1.1.2" + }, + "engines": { + "node": ">=18" } }, - "node_modules/webpack-virtual-modules": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.2.2.tgz", - "integrity": "sha512-kDUmfm3BZrei0y+1NTHJInejzxfhtU8eDj2M7OKb2IWrPFAeO1SOH2KuQ68MSZu9IGEHcxbkKKR1v18FrUSOmA==", - "dev": true, - "dependencies": { - "debug": "^3.0.0" + "node_modules/svelte-chartjs": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/svelte-chartjs/-/svelte-chartjs-4.0.1.tgz", + "integrity": "sha512-4z+0J+w/6ADH2Cy+/AnVek2HxRrznQ7dJfWTybc9BHm9//DCb1BmLrSE3NGDRDLj+kwJbKw2o1tPLBE3CmdHmw==", + "license": "MIT", + "peerDependencies": { + "chart.js": "^3.5.0 || ^4.0.0", + "svelte": "^5.0.0" } }, - "node_modules/webpack-virtual-modules/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/svelte-intersection-observer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/svelte-intersection-observer/-/svelte-intersection-observer-2.2.0.tgz", + "integrity": "sha512-CBu9oEzRt/dbxZeZtTlCb8N6e7Eiet6GOsupS2jNNKuekJ1VLbj1H5Eozs9riHrKNvSYu8fIUpPTWk+6S3x48g==", "dev": true, - "dependencies": { - "ms": "^2.1.1" - } + "license": "MIT" + }, + "node_modules/svelte-loading-spinners": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/svelte-loading-spinners/-/svelte-loading-spinners-0.3.6.tgz", + "integrity": "sha512-mthHQ2TwiwzTWzbFry3CBnVEfzqPOD9WkVw84OfSYzHRq6N9wgQ+yv37u81uPeuLU/ZOIPqhujpXquB1aol5ZQ==", + "license": "MIT" + }, + "node_modules/svelte-routing": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/svelte-routing/-/svelte-routing-2.13.0.tgz", + "integrity": "sha512-/NTxqTwLc7Dq306hARJrH2HLXOBtKd7hu8nxgoFDlK0AC4SOKnzisiX/9m8Uksei1QAWtlAEdF91YphNM8iDMg==", + "license": "MIT" }, - "node_modules/webpack/node_modules/acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", "dev": true, - "bin": { - "acorn": "bin/acorn" - }, + "license": "MIT", "engines": { - "node": ">=0.4.0" + "node": ">=12.0.0" } }, - "node_modules/webpack/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "node_modules/svg2ttf": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/svg2ttf/-/svg2ttf-6.1.0.tgz", + "integrity": "sha512-EjxgcmhKcBpx/3fR1hPwVtJAbUc/ZsDpwOTF74SI3PbzCg4pDHnxVmoSuqgEqxVJGqqkSCI6+82cucpn2D5aOw==", "dev": true, + "license": "MIT", "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "@xmldom/xmldom": "^0.9.10", + "argparse": "^2.0.1", + "cubic2quad": "^1.2.1", + "lodash": "^4.17.10", + "microbuffer": "^1.0.0", + "svgpath": "^2.1.5" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "svg2ttf": "svg2ttf.js" } }, - "node_modules/webpack/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "node_modules/svgicons2svgfont": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/svgicons2svgfont/-/svgicons2svgfont-10.0.6.tgz", + "integrity": "sha512-fUgQEVg3XwTbOHvlXahHGqCet5Wvfo1bV4DCvbSRvjsOCPCRunYbG4dUJCPegps37BMph3eOrfoobhH5AWuC6A==", "dev": true, + "license": "MIT", "dependencies": { - "is-extendable": "^0.1.0" + "commander": "^7.2.0", + "geometry-interfaces": "^1.1.4", + "glob": "^7.1.6", + "neatequal": "^1.0.0", + "readable-stream": "^3.4.0", + "sax": "^1.2.4", + "svg-pathdata": "^6.0.0" + }, + "bin": { + "svgicons2svgfont": "bin/svgicons2svgfont.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=12.0.0" } }, - "node_modules/webpack/node_modules/cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "node_modules/svgpath": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/svgpath/-/svgpath-2.6.0.tgz", + "integrity": "sha512-OIWR6bKzXvdXYyO4DK/UWa1VA1JeKq8E+0ug2DG98Y/vOmMpfZNj+TIG988HjfYSqtcy/hFOtZq/n/j5GSESNg==", "dev": true, - "dependencies": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" + "license": "MIT", + "funding": { + "url": "https://github.com/fontello/svg2ttf?sponsor=1" } }, - "node_modules/webpack/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "node_modules/webpack/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" }, - "node_modules/webpack/node_modules/eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, + "license": "ISC", "dependencies": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "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": ">=4.0.0" + "node": ">=10" } }, - "node_modules/webpack/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, + "license": "ISC", "engines": { - "node": ">=4.0" + "node": ">=8" } }, - "node_modules/webpack/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, + "license": "MIT", "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "fdir": "^6.5.0", + "picomatch": "^4.0.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/webpack/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "node_modules/tldts": { + "version": "7.4.10", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.10.tgz", + "integrity": "sha512-GgouD1B+sWwvkaEq8vXC15DjQitxbvs12oIXELpconwm+Tg3zfcEv4jgzq3vtKverDXsg3VI8aRgNL2Nra0Iog==", "dev": true, + "license": "MIT", "dependencies": { - "is-extendable": "^0.1.0" + "tldts-core": "^7.4.10" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "tldts": "bin/cli.js" } }, - "node_modules/webpack/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "node_modules/tldts-core": { + "version": "7.4.10", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.10.tgz", + "integrity": "sha512-KnQjp53ZekKgm/r3l+u8kJGGzYgrWdP8+Mql7a4vijh2WE0IrZWspQj/TpTxDho/YxO+AnOZnIjQcCD+q6iJsw==", + "dev": true, + "license": "MIT" }, - "node_modules/webpack/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "node_modules/tough-cookie": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.2.tgz", + "integrity": "sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==", "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, "engines": { - "node": ">=0.10.0" + "node": ">=16" } }, - "node_modules/webpack/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", "dev": true, + "license": "MIT", "dependencies": { - "kind-of": "^3.0.2" + "punycode": "^2.3.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=20" } }, - "node_modules/webpack/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "node_modules/ttf2eot": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ttf2eot/-/ttf2eot-3.1.0.tgz", + "integrity": "sha512-aHTbcYosNHVqb2Qtt9Xfta77ae/5y0VfdwNLUS6sGBeGr22cX2JDMo/i5h3uuOf+FAD3akYOr17+fYd5NK8aXw==", "dev": true, + "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5" + "argparse": "^2.0.1" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "ttf2eot": "ttf2eot.js" } }, - "node_modules/webpack/node_modules/is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "node_modules/ttf2woff": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ttf2woff/-/ttf2woff-3.0.0.tgz", + "integrity": "sha512-OvmFcj70PhmAsVQKfC15XoKH55cRWuaRzvr2fpTNhTNer6JBpG8n6vOhRrIgxMjcikyYt88xqYXMMVapJ4Rjvg==", "dev": true, - "engines": { - "node": ">=4" + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "pako": "^1.0.0" + }, + "bin": { + "ttf2woff": "ttf2woff.js" } }, - "node_modules/webpack/node_modules/json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "node_modules/ttf2woff2": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/ttf2woff2/-/ttf2woff2-4.0.5.tgz", + "integrity": "sha512-zpoU0NopfjoyVqkFeQ722SyKk/n607mm5OHxuDS/wCCSy82B8H3hHXrezftA2KMbKqfJIjie2lsJHdvPnBGbsw==", "dev": true, + "hasInstallScript": true, + "license": "MIT", "dependencies": { - "minimist": "^1.2.0" + "bindings": "^1.5.0", + "bufferstreams": "^3.0.0", + "nan": "^2.14.2", + "node-gyp": "^9.0.0" }, "bin": { - "json5": "lib/cli.js" + "ttf2woff2": "bin/ttf2woff2.js" + }, + "engines": { + "node": ">=12" } }, - "node_modules/webpack/node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" }, "engines": { - "node": ">=4.0.0" + "node": ">=0.8.0" } }, - "node_modules/webpack/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==", + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", "dev": true, - "dependencies": { - "yallist": "^3.0.2" + "license": "MIT" + }, + "node_modules/undici": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.0.tgz", + "integrity": "sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.19.0" } }, - "node_modules/webpack/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", "dev": true, + "license": "ISC", "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "unique-slug": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/webpack/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", "dev": true, + "license": "ISC", "dependencies": { - "minimist": "^1.2.6" + "imurmurhash": "^0.1.4" }, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" } }, - "node_modules/webpack/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/varstream": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/varstream/-/varstream-0.3.2.tgz", + "integrity": "sha512-OpR3Usr9dGZZbDttlTxdviGdxiURI0prX68+DuaN/JfIDbK9ZOmREKM6PgmelsejMnhgjXmEEEgf+E4NbsSqMg==", "dev": true, "dependencies": { - "glob": "^7.1.3" + "readable-stream": "^1.0.33" }, "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "json2varstream": "cli/json2varstream.js", + "varstream2json": "cli/varstream2json.js" }, "engines": { - "node": ">= 4" + "node": ">=0.10.*" } }, - "node_modules/webpack/node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "node_modules/varstream/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", "dev": true, + "license": "MIT", "dependencies": { - "randombytes": "^2.1.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, - "node_modules/webpack/node_modules/ssri": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", - "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "node_modules/varstream/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", "dev": true, - "dependencies": { - "figgy-pudding": "^3.5.1" - } + "license": "MIT" }, - "node_modules/webpack/node_modules/terser": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", - "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", + "node_modules/vite": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.1.tgz", + "integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==", "dev": true, + "license": "MIT", "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.25", + "rolldown": "~1.2.1", + "tinyglobby": "^0.2.17" }, "bin": { - "terser": "bin/terser" + "vite": "bin/vite.js" }, "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/webpack/node_modules/terser-webpack-plugin": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", - "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", - "dev": true, - "dependencies": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" + "node": "^20.19.0 || >=22.12.0" }, - "engines": { - "node": ">= 6.9.0" + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" }, - "peerDependencies": { - "webpack": "^4.0.0" - } - }, - "node_modules/webpack/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.4.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, - "engines": { - "node": ">=0.10.0" + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } } }, - "node_modules/webpack/node_modules/watchpack": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", - "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "node_modules/vitefu": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz", + "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==", "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" + "license": "MIT", + "workspaces": [ + "tests/deps/*", + "tests/projects/*", + "tests/projects/workspace/packages/*" + ], + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, - "optionalDependencies": { - "chokidar": "^3.4.1", - "watchpack-chokidar2": "^2.0.1" + "peerDependenciesMeta": { + "vite": { + "optional": true + } } }, - "node_modules/webpack/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/webpack/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/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, "license": "MIT", "dependencies": { - "iconv-lite": "0.6.3" + "xml-name-validator": "^5.0.0" }, "engines": { "node": ">=18" } }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/webidl-conversions": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">=0.10.0" + "node": ">=20" } }, "node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-17.1.0.tgz", + "integrity": "sha512-3GeworPmc2ZfEEHP7lEbUfBX/L75wdEsi0rLNhXcXxnoN5jyq0SL5gCy06SGW2cyTIZdTvWIDQNQoza++vKeaw==", "dev": true, + "license": "MIT", "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "@exodus/bytes": "^1.15.1", + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.1" + }, + "engines": { + "node": "^22.14.0 || >=24.0.0" } }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -25553,198 +4025,29 @@ "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/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", "dev": true, + "license": "ISC", "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "string-width": "^1.0.2 || 2 || 3 || 4" } }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" - }, - "node_modules/worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "dependencies": { - "errno": "~0.1.7" - } - }, - "node_modules/worker-rpc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/worker-rpc/-/worker-rpc-0.1.1.tgz", - "integrity": "sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg==", - "dev": true, - "dependencies": { - "microevent.ts": "~0.1.1" - } - }, - "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/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "license": "MIT" }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "dependencies": { - "mkdirp": "^0.5.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/write/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ws": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", - "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/x-default-browser": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/x-default-browser/-/x-default-browser-0.4.0.tgz", - "integrity": "sha512-7LKo7RtWfoFN/rHx1UELv/2zHGMx8MkZKDq1xENmOCTkfIqZJ0zZ26NEJX8czhnPXVcqS0ARjjfJB+eJ0/5Cvw==", - "dev": true, - "bin": { - "x-default-browser": "bin/x-default-browser.js" - }, - "optionalDependencies": { - "default-browser-id": "^1.0.4" - } + "license": "ISC" }, "node_modules/xml-name-validator": { "version": "5.0.0", @@ -25763,86 +4066,18 @@ "dev": true, "license": "MIT" }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "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": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "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/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==", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "ISC" }, - "node_modules/zwitch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", - "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } + "node_modules/zimmerframe": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz", + "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==", + "license": "MIT" } } } diff --git a/application/frontend/package.json b/application/frontend/package.json index 047e01c..fe1925a 100644 --- a/application/frontend/package.json +++ b/application/frontend/package.json @@ -6,39 +6,29 @@ "scripts": { "dev": "vite", "build": "vite build --base=/ONLOGS_PREFIX_ENV_VARIABLE_THAT_SHOULD_BE_REPLACED_ON_BACKEND_INITIALIZATION ", - "test": "vite build --base=/ONLOGS_PREFIX_ENV_VARIABLE_THAT_SHOULD_BE_REPLACED_ON_BACKEND_INITIALIZATION && node startDebug.js ", + "test": "node scripts/run-tests.mjs", "test:ansi": "node src/utils/ansi.test.mjs", "test:highlight": "node src/Views/Logs/highlight.test.mjs", "preview": "vite preview", - "sb": "start-storybook -p 6006", - "build-storybook": "build-storybook", - "buildfont": "node generate_font.js" + "buildfont": "node generate_font.js", + "debug": "vite build --base=/ONLOGS_PREFIX_ENV_VARIABLE_THAT_SHOULD_BE_REPLACED_ON_BACKEND_INITIALIZATION && node startDebug.js" }, "devDependencies": { - "@babel/core": "^7.19.3", - "@storybook/addon-actions": "^6.5.12", - "@storybook/addon-essentials": "^6.5.12", - "@storybook/addon-interactions": "^6.5.12", - "@storybook/addon-links": "^6.5.12", - "@storybook/builder-vite": "^0.2.3", - "@storybook/svelte": "^6.5.12", - "@storybook/testing-library": "^0.0.13", - "@sveltejs/vite-plugin-svelte": "^1.0.2", - "eslint-plugin-svelte3": "^4.0.0", - "fs-extra": "^11.1.0", - "jsdom": "^24.1.3", - "sass": "^1.55.0", - "svelte": "^3.49.0", - "svelte-intersection-observer": "^0.10.0", - "vite": "^3.1.0" + "@sveltejs/vite-plugin-svelte": "^7.2.0", + "@vusion/webfonts-generator": "^0.8.0", + "esbuild": "^0.28.1", + "fs-extra": "^11.4.0", + "jsdom": "^30.0.1", + "sass": "^1.102.0", + "svelte": "^5.56.8", + "svelte-intersection-observer": "^2.2.0", + "vite": "^8.2.1" }, "dependencies": { - "@vusion/webfonts-generator": "^0.8.0", "ansi-to-html": "^0.7.2", - "chart.js": "^4.2.0", - "json-to-html": "^0.1.2", - "svelte-chartjs": "^3.1.2", - "svelte-loading-spinners": "^0.3.4", - "svelte-routing": "^1.6.0" + "chart.js": "^4.5.1", + "svelte-chartjs": "^4.0.1", + "svelte-loading-spinners": "^0.3.6", + "svelte-routing": "^2.13.0" } } diff --git a/application/frontend/scripts/run-tests.mjs b/application/frontend/scripts/run-tests.mjs new file mode 100644 index 0000000..6c3aa89 --- /dev/null +++ b/application/frontend/scripts/run-tests.mjs @@ -0,0 +1,20 @@ +import { globSync } from "node:fs"; +import { spawnSync } from "node:child_process"; + +const files = globSync("src/**/*.test.mjs").sort(); +if (files.length === 0) { + console.error("no test files matched src/**/*.test.mjs"); + process.exit(1); +} + +let failed = 0; +for (const file of files) { + const result = spawnSync(process.execPath, [file], { stdio: "inherit" }); + if (result.status !== 0) { + console.error(`FAIL ${file}`); + failed += 1; + } +} + +console.log(`\n${files.length - failed}/${files.length} test files passed`); +process.exit(failed === 0 ? 0 : 1); diff --git a/application/frontend/src/App.routing.test.mjs b/application/frontend/src/App.routing.test.mjs new file mode 100644 index 0000000..0ac9c4c --- /dev/null +++ b/application/frontend/src/App.routing.test.mjs @@ -0,0 +1,67 @@ +// svelte-routing tells a component apart from a lazy loader with +// `c.toString().startsWith("class ")`. Svelte 5 compiles components to +// functions, so `` called X instead of rendering it. +import assert from "node:assert/strict"; +import { + bundleComponent, + installDom, + jsonResponse, + settle, + importBundle, + main, +} from "../test/harness.mjs"; + +async function stubFetch(url) { + const target = String(url); + if ( + target.includes("getLogs") || + target.includes("getPrevLogs") || + target.includes("getLogWithPrev") + ) { + return jsonResponse({ logs: [], last_processed_key: "", is_end: true }); + } + return jsonResponse({ error: null }); +} + +const NOT_FOUND = "404 This is not the web page"; + +main(async () => { + // changeKey.js reads `location` at module scope, so the DOM has to exist + // before the bundle is imported. + const outfile = await bundleComponent("test/entry.js"); + installDom({ fetchImpl: stubFetch }); + const bundle = await importBundle(outfile); + + async function mountAt(path) { + const { window } = installDom({ fetchImpl: stubFetch }); + const target = window.document.body; + const app = bundle.mount(bundle.App, { + target, + props: { url: `${bundle.changeKey}${path}` }, + }); + await settle(); + return { app, target }; + } + + const matched = await mountAt("/view/test-host/test-service"); + const matchedText = matched.target.textContent; + console.log(` /view/:host/:service rendered 404: ${matchedText.includes(NOT_FOUND)}`); + assert.ok( + !matchedText.includes(NOT_FOUND), + "/view/:host/:service fell through to the default route" + ); + assert.ok( + matched.target.querySelector(".contentContainer"), + "the matched route rendered nothing" + ); + bundle.unmount(matched.app); + + const unmatched = await mountAt("/no-such-page"); + assert.ok( + unmatched.target.textContent.includes(NOT_FOUND), + "the default route did not render for an unmatched path" + ); + bundle.unmount(unmatched.app); + + console.log("App routing tests passed"); +}); diff --git a/application/frontend/src/App.svelte b/application/frontend/src/App.svelte index 4dc9069..1532efc 100644 --- a/application/frontend/src/App.svelte +++ b/application/frontend/src/App.svelte @@ -10,20 +10,12 @@ lastChosenService, urlHash, } from "./Stores/stores.js"; - import { onMount, onDestroy } from "svelte"; + import { onMount } from "svelte"; import Toast from "./lib/Toast/Toast.svelte"; import Notfound from "./lib/NotFound/Notfound.svelte"; - export let url = ""; - let themeState = "dark"; - let basePathname = ""; - let availibleRoutes = ["view", "login", "users", "servicesettings"]; import { changeKey } from "./utils/changeKey"; import { navigate } from "svelte-routing"; - - const unsubscribe = theme.subscribe((v) => { - themeState = v; - }); - $: themeState && checkTheme(themeState); + let { url = "" } = $props(); function checkTheme(t) { const bodyEl = document.querySelector("body"); @@ -41,8 +33,10 @@ if (LStheme) { theme.set(LStheme); } + const routeNamesContainer = + /\/(view|stats|servicesettings)\/[^/]+\/[^/]+/.test(location.pathname); const LSHostData = window.localStorage.getItem("lsthd"); - if (LSHostData) { + if (LSHostData && !routeNamesContainer) { try { const data = JSON.parse(LSHostData); lastChosenHost.set(data.h); @@ -61,11 +55,7 @@ } else { activeMenuOption.set("home"); } - if (!availibleRoutes.includes(location.pathname.split("/")?.at(1))) { - basePathname = location.pathname.split("/")?.at(1); - } }); - onDestroy(unsubscribe); function writeLastChosenHostToLS() { window.localStorage.setItem( @@ -74,24 +64,42 @@ ); } - $: { + $effect(() => { + checkTheme($theme); + }); + + $effect(() => { if ($lastChosenHost && $lastChosenService) { writeLastChosenHostToLS(); } - } + });
- - - - - - + + + {#snippet children({ params })} +
+ {/snippet} + + +
+ + {#snippet children({ params })} +
+ {/snippet} + + + {#snippet children({ params })} +
+ {/snippet} + +
-
{#if $toastIsVisible} {/if}
diff --git a/application/frontend/src/Stores/stores.js b/application/frontend/src/Stores/stores.js index f47e58b..7d1d3dd 100644 --- a/application/frontend/src/Stores/stores.js +++ b/application/frontend/src/Stores/stores.js @@ -25,6 +25,15 @@ export const theme = writable("light"); export const lastChosenHost = writable(""); export const lastChosenService = writable(""); +export const hostAliases = writable({}); +export const hostBeingRenamed = writable(null); + +// service groups, loaded from /api/v1/getGroups +export const groups = writable([]); +export const groupModalIsVisible = writable(false); +// The group being edited, or null when the modal is creating a new one. +export const groupBeingEdited = writable(null); + // toast state export const toast = writable({ @@ -52,7 +61,8 @@ export const listScrollIsVisible = writable(false); //confirmation menu export const confirmationObj = writable({ - action: function () {}, + // null means "the default clear-logs flow"; a function replaces it. + action: null, message: "You want to delete host service logs. This data will be lost. This action cannot be undone.", @@ -68,7 +78,7 @@ export const lastLogTimestamp = writable(0); //stats export const lastStatsPeriod = writable(2); -export const lastStatisticPeriod = writable("Per hour"); +export const lastStatisticPeriod = writable("hour"); //spiner diff --git a/application/frontend/src/Theme.scss b/application/frontend/src/Theme.scss index 7521f2d..97f4b16 100644 --- a/application/frontend/src/Theme.scss +++ b/application/frontend/src/Theme.scss @@ -63,6 +63,17 @@ color: inherit; } } + // The generic `input:focus` rule above drops the border colour, which a + // nested .groupModal selector would outrank; restore the ring in dark accent. + .groupModal { + .groupNameInput:focus { + border-color: $active-color-dark; + } + .groupModalService input[type="checkbox"] { + accent-color: $active-color-dark; + color-scheme: dark; + } + } .contentContainer { h1#title { color: $active-color-dark; diff --git a/application/frontend/src/Views/Login/Login.svelte b/application/frontend/src/Views/Login/Login.svelte index 85685c0..4f95199 100644 --- a/application/frontend/src/Views/Login/Login.svelte +++ b/application/frontend/src/Views/Login/Login.svelte @@ -8,8 +8,8 @@ let api = new fetchApi(); let result = true; - let wrong = "", - message = ""; + let wrong = $state(""), + message = $state(""); let cookies = document.cookie.split(";"); for (const cookie of cookies) { @@ -52,7 +52,7 @@ name="login" class={wrong} placeholder="login" - on:click={() => { + onclick={() => { wrong = ""; }} /> @@ -62,7 +62,7 @@ class={wrong} id="password" placeholder="password" - on:click={() => { + onclick={() => { wrong = ""; }} /> @@ -81,4 +81,4 @@ - + diff --git a/application/frontend/src/Views/Logs/LogStringHeader.svelte b/application/frontend/src/Views/Logs/LogStringHeader.svelte deleted file mode 100644 index 1c03d81..0000000 --- a/application/frontend/src/Views/Logs/LogStringHeader.svelte +++ /dev/null @@ -1,7 +0,0 @@ - - -
diff --git a/application/frontend/src/Views/Logs/LogsView.scss b/application/frontend/src/Views/Logs/LogsView.scss index 88ebb08..16c56f3 100644 --- a/application/frontend/src/Views/Logs/LogsView.scss +++ b/application/frontend/src/Views/Logs/LogsView.scss @@ -35,18 +35,6 @@ div .chosen { border-radius: $main-border-radius; } } -.logStringHeaderContainer { - position: absolute; - top: 12px; - right: 8px; - z-index: 7; - opacity: 0.4; - &:hover { - opacity: 1; - cursor: pointer; - } -} - .logsTable { width: 100%; position: relative; @@ -83,30 +71,11 @@ h2.noLogsMessage { color: #a3a3b9; } -.show { - box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.15); - border-radius: 10px; - background-color: rgba(0, 0, 0, 0); - height: 42px; - width: 42px; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - - .icon { - display: flex; - align-items: center; - vertical-align: bottom; - - .log.log-Eye::before { - font-size: 25px; - } - } -} .searchIcoContainer { position: absolute; left: 16px; + // Decorative: it sits over the field, so let clicks through to focus it. + pointer-events: none; } .search { @@ -122,7 +91,9 @@ h2.noLogsMessage { font-size: $main-font-m; background-color: $inpun-color; border-radius: 10px; - padding: 0 14px 0 14px; + // Left padding clears the search icon, which is pinned at 16px inside the + // field; at 14px the text ran underneath it. + padding: 0 14px 0 40px; height: 40px; border: 1px solid $text-placeholder-color; @@ -132,12 +103,6 @@ h2.noLogsMessage { border: 2px solid $active-color; // caret-color: transparent; } - input::placeholder { - position: absolute; - left: 40px; - top: 50%; - transform: translate(0, -50%); - } } .logs { @@ -199,58 +164,3 @@ h2.noLogsMessage { } } -.lds-ellipsis { - display: flex; - align-self: center; - justify-content: center; - position: relative; - height: 10px; -} -.lds-ellipsis div { - position: absolute; - width: 8px; - height: 8px; - border-radius: 50%; - background: #4e49da; - animation-timing-function: cubic-bezier(0, 1, 1, 0); -} -.lds-ellipsis div:nth-child(1) { - left: 8px; - animation: lds-ellipsis1 0.6s infinite; -} -.lds-ellipsis div:nth-child(2) { - left: 8px; - animation: lds-ellipsis2 0.6s infinite; -} -.lds-ellipsis div:nth-child(3) { - left: 32px; - animation: lds-ellipsis2 0.6s infinite; -} -.lds-ellipsis div:nth-child(4) { - left: 56px; - animation: lds-ellipsis3 0.6s infinite; -} -@keyframes lds-ellipsis1 { - 0% { - transform: scale(0); - } - 100% { - transform: scale(1); - } -} -@keyframes lds-ellipsis3 { - 0% { - transform: scale(1); - } - 100% { - transform: scale(0); - } -} -@keyframes lds-ellipsis2 { - 0% { - transform: translate(0, 0); - } - 100% { - transform: translate(24px, 0); - } -} diff --git a/application/frontend/src/Views/Logs/LogsViewHeder/LogsViewHeder.svelte b/application/frontend/src/Views/Logs/LogsViewHeder/LogsViewHeder.svelte index 90b1fbb..86762a8 100644 --- a/application/frontend/src/Views/Logs/LogsViewHeder/LogsViewHeder.svelte +++ b/application/frontend/src/Views/Logs/LogsViewHeder/LogsViewHeder.svelte @@ -1,16 +1,16 @@
@@ -45,7 +50,7 @@
diff --git a/application/frontend/src/Views/Logs/LogsViewHeder/LogsViewHeder.test.mjs b/application/frontend/src/Views/Logs/LogsViewHeder/LogsViewHeder.test.mjs new file mode 100644 index 0000000..ebd4b95 --- /dev/null +++ b/application/frontend/src/Views/Logs/LogsViewHeder/LogsViewHeder.test.mjs @@ -0,0 +1,69 @@ +import assert from "node:assert/strict"; +import { + bundleComponent, + installDom, + settle, + importBundle, + main, +} from "../../../../test/harness.mjs"; + +const DEBOUNCE_MS = 750; + +function type(window, input, value) { + input.value = value; + input.dispatchEvent(new window.Event("input", { bubbles: true })); +} + +main(async () => { + const bundlePath = await bundleComponent("test/entry.js"); + const { window } = installDom({}); + const bundle = await importBundle(bundlePath); + + const target = window.document.body; + const props = bundle.reactiveProps({ searchText: "", searchResetVersion: 0 }); + const component = bundle.mount(bundle.LogsViewHeder, { target, props }); + + const observed = []; + + const input = target.querySelector("input[type=text]"); + assert.ok(input, "the search input should be rendered"); + + const word = "error"; + for (let i = 1; i <= word.length; i++) { + type(window, input, word.slice(0, i)); + await settle(2); + observed.push(props.searchText); + } + + console.log(` searchText after ${word.length} keystrokes: ${JSON.stringify(observed)}`); + + assert.deepEqual( + observed, + new Array(word.length).fill(""), + `each keystroke updated searchText immediately (${JSON.stringify(observed)}), ` + + `so every character starts a full reload` + ); + + await new Promise((resolve) => setTimeout(resolve, DEBOUNCE_MS + 250)); + assert.equal( + props.searchText, + word, + `searchText should be ${JSON.stringify(word)} after the debounce window, got ` + + JSON.stringify(props.searchText) + ); + + // A pending timer must not write back after the view clears the search, or a + // service switch reloads the new service filtered by the old term. + type(window, input, "stale term"); + props.searchResetVersion = props.searchResetVersion + 1; + await new Promise((resolve) => setTimeout(resolve, DEBOUNCE_MS + 250)); + + assert.notEqual( + props.searchText, + "stale term", + "a pending debounce timer resurrected the previous search term after it was cleared" + ); + + bundle.unmount(component); + console.log("LogsViewHeder debounce tests passed"); +}); diff --git a/application/frontend/src/Views/Logs/NewLogsV2.pagination.test.mjs b/application/frontend/src/Views/Logs/NewLogsV2.pagination.test.mjs new file mode 100644 index 0000000..68402bc --- /dev/null +++ b/application/frontend/src/Views/Logs/NewLogsV2.pagination.test.mjs @@ -0,0 +1,123 @@ +// Drives every scroll interceptor in the log view: the rendered window must stay +// bounded and no log line may ever be on screen twice. +import assert from "node:assert/strict"; +import { + bundleComponent, + installDom, + jsonResponse, + settle, + importBundle, + main, +} from "../../../test/harness.mjs"; + +const LIMIT = 60; + +let nextIndex = 0; + +// Distinct, strictly decreasing keys, as the backend emits them. +function makePage(count) { + return Array.from({ length: count }, () => { + const idx = nextIndex++; + const nanos = String(999999999 - idx * 1000).padStart(9, "0"); + return [`2026-02-10T12:44:03.${nanos}Z`, `line-${idx}`]; + }); +} + +function limitFromUrl(url) { + const match = /[?&]limit=(\d+)/.exec(String(url)); + return match ? Number(match[1]) : LIMIT; +} + +function stubFetch(counter) { + return async (url) => { + const target = String(url); + if (target.includes("getLogs?")) { + counter.getLogs += 1; + const rows = makePage(limitFromUrl(target)); + return jsonResponse({ + logs: rows, + last_processed_key: rows.at(-1)[0], + is_end: false, + }); + } + // Nothing newer than what is already on screen. + return jsonResponse({ logs: [], last_processed_key: "", is_end: true }); + }; +} + +function renderedMessages(target) { + return [...target.querySelectorAll(".message p")] + .map((el) => el.textContent.trim()) + .filter((text) => text.startsWith("line-")); +} + +function assertInvariants(target, label) { + const messages = renderedMessages(target); + const unique = new Set(messages); + + assert.equal( + unique.size, + messages.length, + `${label}: the same log line is on screen more than once ` + + `(${messages.length} rows, ${unique.size} distinct)` + ); + assert.ok( + messages.length <= 3 * LIMIT, + `${label}: the rendered window grew past 3x the page size ` + + `(${messages.length} rows); it should slide, not accumulate` + ); + return messages; +} + +main(async () => { + const counter = { getLogs: 0 }; + const { window } = installDom({ fetchImpl: stubFetch(counter) }); + const bundle = await importBundle(await bundleComponent("test/entry.js")); + + bundle.lastChosenHost.set("testhost"); + bundle.lastChosenService.set("testservice"); + bundle.isPending.set(false); + + const target = window.document.body; + const component = bundle.mount(bundle.NewLogsV2, { target }); + + await settle(40); + // The view only arms its interceptors once initialScroll flips, on a 1s timer. + await new Promise((resolve) => setTimeout(resolve, 1400)); + await settle(10); + + const initial = assertInvariants(target, "initial load"); + console.log(` initial load: ${initial.length} rows, ${counter.getLogs} request(s)`); + assert.equal(initial.length, 3 * LIMIT, "expected three pages on screen"); + + const observers = globalThis.__onlogsObservers || []; + assert.ok(observers.length > 0, "no interceptors were registered"); + + let triggered = 0; + for (let i = 0; i < observers.length; i++) { + const before = counter.getLogs; + observers[i].set(true); + await settle(10); + observers[i].set(false); + await settle(5); + + if (counter.getLogs !== before) { + triggered += 1; + const rows = assertInvariants(target, `after interceptor ${i}`); + console.log( + ` interceptor ${i}: +${counter.getLogs - before} request(s), ${rows.length} rows` + ); + } + } + + assert.ok( + triggered > 0, + "no interceptor triggered a fetch, so upward pagination was not exercised" + ); + + const finalRows = assertInvariants(target, "final"); + console.log(` after ${triggered} interceptor firing(s): ${finalRows.length} rows`); + + bundle.unmount(component); + console.log("NewLogsV2 pagination tests passed"); +}); diff --git a/application/frontend/src/Views/Logs/NewLogsV2.requeststorm.test.mjs b/application/frontend/src/Views/Logs/NewLogsV2.requeststorm.test.mjs new file mode 100644 index 0000000..dac7737 --- /dev/null +++ b/application/frontend/src/Views/Logs/NewLogsV2.requeststorm.test.mjs @@ -0,0 +1,157 @@ +// A sentinel that stays in view must cost at most one request per endpoint once +// the backend has nothing left to give. +// +// The backend models the established contract: getLogs pages toward OLDER rows +// and returns them newest-first, getPrevLogs pages toward NEWER rows. The corpus +// is exactly one rendered window, so both directions are already exhausted. +import assert from "node:assert/strict"; +import { + bundleComponent, + installDom, + jsonResponse, + settle, + importBundle, + main, +} from "../../../test/harness.mjs"; + +const LIMIT = 60; +const CORPUS = 3 * LIMIT; + +// index 0 = newest. The third element is the full storage key logKey() reads. +const ROWS = Array.from({ length: CORPUS }, (_, i) => { + const nanos = String(999999999 - i * 1000).padStart(9, "0"); + const ts = `2026-08-07T16:14:16.${nanos}Z`; + return [ts, `line-${i}`, `${ts} +1786119256365958477-${44159 - i}`]; +}); +const INDEX_OF = new Map(ROWS.map((row, i) => [row[2], i])); + +const counter = { getLogs: 0, getPrevLogs: 0 }; +const seen = { getLogs: new Set(), getPrevLogs: new Set() }; + +const fetchImpl = async (url) => { + const target = String(url); + const params = new URL(target, "http://onlogs.test").searchParams; + const limit = Number(params.get("limit")) || LIMIT; + const startWith = params.get("startWith") || ""; + + if (target.includes("getPrevLogs?")) { + counter.getPrevLogs += 1; + seen.getPrevLogs.add(target); + const i = INDEX_OF.get(startWith) ?? 0; + const rows = ROWS.slice(Math.max(0, i - limit), i).reverse(); + return jsonResponse({ + logs: rows, + last_processed_key: rows.at(-1)?.[2] ?? startWith, + is_end: i - limit <= 0, + }); + } + + if (target.includes("getLogs?")) { + counter.getLogs += 1; + seen.getLogs.add(target); + const start = startWith ? (INDEX_OF.get(startWith) ?? -1) + 1 : 0; + const rows = ROWS.slice(start, start + limit); + return jsonResponse({ + logs: rows, + last_processed_key: rows.at(-1)?.[2] ?? startWith, + is_end: start + limit >= CORPUS, + }); + } + + return jsonResponse({ logs: [], last_processed_key: "", is_end: true }); +}; + +function renderedMessages(target) { + return [...target.querySelectorAll(".message p")] + .map((el) => el.textContent.trim()) + .filter((text) => text.startsWith("line-")); +} + +// Holds each sentinel in turn until one of them fetches, and leaves it held β€” +// which is what a real IntersectionObserver does while the sentinel is on screen. +async function holdTheFetchingSentinel(endpoint) { + const observers = globalThis.__onlogsObservers || []; + assert.ok(observers.length > 0, "no interceptors were registered"); + + for (const handle of observers) { + const before = counter[endpoint]; + handle.set(true); + await settle(6); + if (counter[endpoint] > before) { + return handle; + } + handle.set(false); + await settle(2); + } + assert.fail(`no interceptor triggered ${endpoint}`); +} + +async function idleRequests(endpoint, rounds) { + const before = counter[endpoint]; + await settle(rounds); + return counter[endpoint] - before; +} + +main(async () => { + const { window } = installDom({ fetchImpl }); + const bundle = await importBundle(await bundleComponent("test/entry.js")); + + bundle.lastChosenHost.set("rmalenko-XPS-15-9530"); + bundle.lastChosenService.set("crash-app"); + bundle.isPending.set(false); + + const target = window.document.body; + const component = bundle.mount(bundle.NewLogsV2, { target }); + + await settle(40); + // The interceptors only arm once initialScroll flips, on a 1s timer. + await new Promise((resolve) => setTimeout(resolve, 1400)); + await settle(10); + + const rows = renderedMessages(target); + assert.equal(rows.length, CORPUS, "expected three pages on screen"); + // getFullLogsSet reverses each newest-first page, so the window is oldest-first. + assert.equal(rows.at(0), `line-${CORPUS - 1}`); + assert.equal(rows.at(-1), "line-0"); + + // Scrolling up: fetchedLogs asks getLogs for rows older than the oldest one. + const upSentinel = await holdTheFetchingSentinel("getLogs"); + const idleGetLogs = await idleRequests("getLogs", 60); + console.log( + ` getLogs while the sentinel sat still: +${idleGetLogs} request(s) over 60 idle ticks` + ); + upSentinel.set(false); + await settle(5); + + // Scrolling down: unfetchedLogs asks getPrevLogs for rows newer than the newest. + const logsEl = window.document.querySelector("#logs"); + Object.defineProperty(logsEl, "scrollTop", { value: 500, configurable: true }); + logsEl.dispatchEvent(new window.Event("scroll")); + await settle(3); + + const downSentinel = await holdTheFetchingSentinel("getPrevLogs"); + const idleGetPrevLogs = await idleRequests("getPrevLogs", 60); + console.log( + ` getPrevLogs while the sentinel sat still: +${idleGetPrevLogs} request(s) over 60 idle ticks` + ); + downSentinel.set(false); + await settle(5); + + assert.equal( + renderedMessages(target).length, + CORPUS, + "empty responses must leave the rendered window alone" + ); + + bundle.unmount(component); + + assert.ok( + idleGetLogs === 0 && idleGetPrevLogs === 0, + `request storm: the view kept fetching with nothing changing β€” ` + + `getLogs +${idleGetLogs}, getPrevLogs +${idleGetPrevLogs} over 60 idle ticks ` + + `(${counter.getLogs} getLogs / ${seen.getLogs.size} distinct, ` + + `${counter.getPrevLogs} getPrevLogs / ${seen.getPrevLogs.size} distinct)` + ); + + console.log("NewLogsV2 request-storm tests passed"); +}); diff --git a/application/frontend/src/Views/Logs/NewLogsV2.sharecopy.test.mjs b/application/frontend/src/Views/Logs/NewLogsV2.sharecopy.test.mjs new file mode 100644 index 0000000..74a67aa --- /dev/null +++ b/application/frontend/src/Views/Logs/NewLogsV2.sharecopy.test.mjs @@ -0,0 +1,115 @@ +import assert from "node:assert/strict"; +import { + bundleComponent, + installDom, + jsonResponse, + settle, + importBundle, + main, +} from "../../../test/harness.mjs"; + +const ROWS = Array.from({ length: 90 }, (_, i) => { + const nanos = String(900000000 - i * 1000).padStart(9, "0"); + const ts = `2026-02-10T12:44:03.${nanos}Z`; + return [ts, `line-${i}`, `${ts} +1786123141845584283-${9000 - i}`]; +}); + +function stubFetch(counter) { + return async (url) => { + const target = String(url); + if (target.includes("getLogWithPrev?")) { + counter.withPrev += 1; + return jsonResponse({ logs: [], last_processed_key: "", is_end: true }); + } + if (target.includes("getPrevLogs?")) { + counter.getPrevLogs += 1; + return jsonResponse({ logs: [], last_processed_key: "", is_end: true }); + } + if (target.includes("getLogs?")) { + counter.getLogs += 1; + const limit = Number(/[?&]limit=(\d+)/.exec(target)?.[1] || 60); + const rows = ROWS.slice(0, limit).map((r) => [...r]); + return jsonResponse({ + logs: rows, + last_processed_key: rows.at(-1)[2], + is_end: false, + }); + } + return jsonResponse({ logs: [], last_processed_key: "", is_end: true }); + }; +} + +function renderedMessages(target) { + return [...target.querySelectorAll(".message p")] + .map((el) => el.textContent.trim()) + .filter((text) => text.startsWith("line-")); +} + +main(async () => { + const counter = { getLogs: 0, getPrevLogs: 0, withPrev: 0 }; + const { window } = installDom({ fetchImpl: stubFetch(counter) }); + + let copied = null; + Object.defineProperty(window.navigator, "clipboard", { + configurable: true, + value: { writeText: async (text) => { copied = text; } }, + }); + globalThis.navigator = window.navigator; + + const bundle = await importBundle(await bundleComponent("test/entry.js")); + bundle.lastChosenHost.set("testhost"); + bundle.lastChosenService.set("testservice"); + bundle.isPending.set(false); + bundle.urlHash.set(""); + + const target = window.document.body; + const component = bundle.mount(bundle.NewLogsV2, { target }); + await settle(40); + await new Promise((resolve) => setTimeout(resolve, 1200)); + await settle(10); + + const before = { + rows: renderedMessages(target), + requests: counter.getLogs + counter.getPrevLogs + counter.withPrev, + }; + assert.ok(before.rows.length > 0, "no log rows rendered, nothing to share"); + + const shareButton = target.querySelector(".shareLinkButtonThumb"); + assert.ok(shareButton, "the share-link button did not render"); + shareButton.click(); + await settle(40); + + const after = { + rows: renderedMessages(target), + requests: counter.getLogs + counter.getPrevLogs + counter.withPrev, + }; + let pending = false; + bundle.isPending.subscribe((v) => (pending = v))(); + + console.log(` copied: ${copied}`); + console.log( + ` requests before/after: ${before.requests}/${after.requests}, ` + + `rows before/after: ${before.rows.length}/${after.rows.length}` + ); + + assert.ok(copied, "clicking the share button copied nothing"); + assert.ok( + copied.includes("#"), + `the copied link carries no log anchor: ${copied}` + ); + + assert.equal( + after.requests, + before.requests, + "sharing a link refetched logs; copying must not reload the view" + ); + assert.deepEqual( + after.rows, + before.rows, + "sharing a link changed the rendered rows; copying must leave the view alone" + ); + assert.equal(pending, false, "sharing a link put the view back into its loading state"); + + bundle.unmount(component); + console.log("share-link copy tests passed"); +}); diff --git a/application/frontend/src/Views/Logs/NewLogsV2.sharedlink.test.mjs b/application/frontend/src/Views/Logs/NewLogsV2.sharedlink.test.mjs new file mode 100644 index 0000000..c6e0ba0 --- /dev/null +++ b/application/frontend/src/Views/Logs/NewLogsV2.sharedlink.test.mjs @@ -0,0 +1,105 @@ +import assert from "node:assert/strict"; +import { + bundleComponent, + installDom, + jsonResponse, + settle, + importBundle, + main, +} from "../../../test/harness.mjs"; + +const LINKED = "2026-02-10T09:00:05.000000000Z"; + +const WINDOW_ROWS = [ + [LINKED, "linked-row", LINKED + " +1-1"], + ["2026-02-10T09:00:04.000000000Z", "window-older", "2026-02-10T09:00:04.000000000Z +1-2"], +]; +const NEWEST_ROWS = [ + ["2026-02-10T18:00:00.000000000Z", "newest-page-row", "2026-02-10T18:00:00.000000000Z +1-3"], +]; + +function stubFetch(counter, latency) { + return async (url) => { + const target = String(url); + if (latency) { + await new Promise((resolve) => setTimeout(resolve, latency)); + } + if (target.includes("getLogWithPrev?")) { + counter.withPrev += 1; + return jsonResponse({ + logs: WINDOW_ROWS.map((r) => [...r]), + last_processed_key: WINDOW_ROWS.at(-1)[2], + is_end: true, + }); + } + if (target.includes("getPrevLogs?")) { + return jsonResponse({ logs: [], last_processed_key: "", is_end: true }); + } + if (target.includes("getLogs?")) { + counter.getLogs += 1; + return jsonResponse({ + logs: NEWEST_ROWS.map((r) => [...r]), + last_processed_key: NEWEST_ROWS[0][2], + is_end: true, + }); + } + return jsonResponse({ error: null }); + }; +} + +function renderedMessages(target) { + return [...target.querySelectorAll(".message p")] + .map((el) => el.textContent.trim()) + .filter(Boolean); +} + +// Set up the DOM before the bundle is imported: fetch.js reads document.location +// at construction. +installDom({}); +const bundle = await importBundle(await bundleComponent("test/entry.js")); + +function openDeepLink(latency) { + const counter = { getLogs: 0, withPrev: 0 }; + const { window } = installDom({ fetchImpl: stubFetch(counter, latency) }); + + bundle.lastChosenHost.set("testhost"); + bundle.lastChosenService.set("testservice"); + bundle.isPending.set(false); + // App.svelte publishes the hash before this component mounts. + bundle.urlHash.set("#" + LINKED); + + const target = window.document.body; + const component = bundle.mount(bundle.NewLogsV2, { target }); + return { component, target, counter }; +} + +main(async () => { + // The deep link must win regardless of how the three concurrent loads + // interleave, so exercise a range of response latencies. + for (const latency of [0, 5, 20]) { + const opened = openDeepLink(latency); + await settle(latency ? 120 : 40); + + const seen = renderedMessages(opened.target); + console.log( + ` latency ${latency}ms -> ${JSON.stringify(seen)} (getLogWithPrev ${opened.counter.withPrev}, getLogs ${opened.counter.getLogs})` + ); + + assert.ok( + opened.counter.withPrev > 0, + `latency ${latency}ms: the deep-link fetch never ran` + ); + assert.ok( + seen.includes("linked-row"), + `latency ${latency}ms: the linked row is not on screen: ${JSON.stringify(seen)}` + ); + assert.ok( + !seen.includes("newest-page-row"), + `latency ${latency}ms: the newest page overwrote the deep-link window: ${JSON.stringify(seen)}` + ); + + bundle.unmount(opened.component); + } + + console.log("shared link deep-link window tests passed"); +}); diff --git a/application/frontend/src/Views/Logs/NewLogsV2.svelte b/application/frontend/src/Views/Logs/NewLogsV2.svelte index 5310a0f..f65cac7 100644 --- a/application/frontend/src/Views/Logs/NewLogsV2.svelte +++ b/application/frontend/src/Views/Logs/NewLogsV2.svelte @@ -3,21 +3,17 @@ import LogsString from "../../lib/LogsString/LogsString.svelte"; import fetchApi from "../../utils/fetch"; - import { navigate } from "svelte-routing"; - import { afterUpdate, onMount, tick } from "svelte"; + import { onDestroy, onMount, tick } from "svelte"; + import { get } from "svelte/store"; import LogsViewHeder from "./LogsViewHeder/LogsViewHeder.svelte"; import IntersectionObserver from "svelte-intersection-observer"; import Spiner from "./Spiner.svelte"; import Loader from "./Loader.svelte"; - import LogStringHeader from "./LogStringHeader.svelte"; import { fade } from "svelte/transition"; import { handleKeydown, copyCustomText } from "../../utils/functions.js"; import { findSearchTextInLogs } from "../../Views/Logs/functions.js"; - import { applySharedLogUrl, buildSharedLogUrl } from "./shareLink.js"; - import { - shouldAutoScrollLogs, - shouldFlushBufferedLogs, - } from "./shareLinkViewState.js"; + import { buildSharedLogUrl } from "./shareLink.js"; + import { createLogsViewFlags } from "./shareLinkViewState.js"; import { store, @@ -48,51 +44,55 @@ scrollToNewLogsEnd, scrollToSpecificLog, } from "./functions"; - import { debug } from "svelte/internal"; const api = new fetchApi(); let visibleLogs = []; let newLogs = []; let previousLogs = []; - let allLogs = []; + let allLogs = $state([]); let webSocket = null; - let logsFromWS = []; + let logsFromWS = $state([]); - let elements = []; - let intersects = []; + let elements = $state([]); + // Dense: binding a hole into IntersectionObserver's `intersecting` throws. + let intersects = $state([false, false, false, false]); - let dateEls = []; - let dateIntersects = []; + let dateEls = $state([]); + let dateIntersects = $state([]); let lastVisibleEl = null; - let endOffLogs = null; - let startOfLogs = null; - let startOfLogsIntersect = null; - let endOffLogsIntersect = null; + let endOffLogs = $state(null); + let startOfLogs = $state(null); + let startOfLogsIntersect = $state(null); + let endOffLogsIntersect = $state(null); let initialScroll = 0; let lastScrollTop = 0; - let scrollDirection = "up"; - let pinedDate = ";"; + let scrollDirection = $state("up"); + let pinedDate = $state(";"); let lastFetchActionIsFetch = true; - let scrollFromButton = false; + let scrollFromButton = $state(false); let stopLogsUnfetch = false; - let mouseDownBlockFetch = false; - let extremalScrollId = ""; + let mouseDownBlockFetch = $state(false); + let extremalScrollId = $state(""); + // Not $state: the interceptor effects read this guard, so clearing it would + // re-run them and refire the fetch it was meant to hold back. let interceptorsWait = false; - let autoscroll = false; - let div; - let getFullLogsSetIsTrottle = false; + let autoscroll = $state(false); + let div = $state(); + let logsLoadGeneration = 0; + // Deliberately an object field: assigning a `let` here would retrigger the very + // reactive blocks this is meant to hold back. + const viewFlags = createLogsViewFlags(); let pauseWS = false; - let newLogsAmount = 1; + let newLogsAmount = $state(1); let controller = null; let signal = null; let topFetchIsStarted = false; + // Latched once the server reports there is nothing older than what is loaded. + let startOfHistoryReached = false; let pinedBadgeTimer = null; - let pinedBadgeIsVisible = false; - let skipNextSearchReload = false; - let skipNextStatusReload = false; - let searchResetVersion = 0; - let isSharedLinkFocusMode = false; + let pinedBadgeIsVisible = $state(false); + let searchResetVersion = $state(0); function refreshStatus() { chosenStatus.set(""); @@ -121,21 +121,39 @@ } } - $: { - if (dateIntersects) { - findLastVisibleLog(); - } - } + //fetch params: - let searchText = ""; - let limit = 60; + let searchText = $state(""); + let limit = $state(60); let startWith = ""; let tmpStartWith = []; + // The third element is the full storage key: the only unique row identity. + const logKey = (logItem) => logItem?.at(2) ?? logItem?.at(0) ?? ""; + + // Dropping repeats by key makes a recurrence visible as a missing row rather + // than a doubled one, and lets the {#each} be keyed. + function dedupeLogs(rows) { + const seen = new Set(); + const unique = []; + for (const row of rows) { + const key = logKey(row); + if (key) { + if (seen.has(key)) { + continue; + } + seen.add(key); + } + unique.push(row); + } + return unique; + } + function resetAllLogs() { + startOfHistoryReached = false; allLogs = []; newLogs = []; visibleLogs = []; @@ -144,44 +162,67 @@ } async function getFullLogsSet() { - if (!getFullLogsSetIsTrottle && $lastChosenService) { - const initialService = $lastChosenService; - pauseWS = true; - let total_logs_amount = 0; - let last_key = ""; - let is_all_logs_processed = false; - while (total_logs_amount < limit && !is_all_logs_processed) { - isSearching.set(true); - let data = await api.getLogs({ - containerName: $lastChosenService, - hostName: $lastChosenHost, - limit: limit * 3, - search: searchText, - caseSens: !$store.caseInSensitive, - status: $chosenStatus, - startWith: last_key, - }) - last_key = data.last_processed_key; - is_all_logs_processed = data.is_end; - total_logs_amount += data.logs.length; + if (!$lastChosenService) { + return; + } - if (initialService === $lastChosenService) { - setLastLogTime(data.logs?.at(0)?.at(0)); - allLogs = [...allLogs, ...data.logs.reverse()]; - let allLogsCopy = [...allLogs]; + const initialService = $lastChosenService; + const generation = ++logsLoadGeneration; + pauseWS = true; + + let acc = []; + let total_logs_amount = 0; + let last_key = ""; + let is_all_logs_processed = false; + + try { + while (total_logs_amount < limit && !is_all_logs_processed) { + isSearching.set(true); + const data = await api.getLogs({ + containerName: $lastChosenService, + hostName: $lastChosenHost, + limit: limit * 3, + search: searchText, + caseSens: !$store.caseInSensitive, + status: $chosenStatus, + startWith: last_key, + }); - newLogs = allLogsCopy.splice(0, limit); + // A newer load, or a service switch, has superseded this one. + if (generation !== logsLoadGeneration || initialService !== $lastChosenService) { + return; + } - visibleLogs = allLogsCopy.splice(0, limit); - previousLogs = allLogsCopy.splice(0, limit); - } + last_key = data.last_processed_key; + is_all_logs_processed = data.is_end; + total_logs_amount += data.logs.length; + + if (!data.logs.length) { + break; } + + setLastLogTime(data.logs?.at(0)?.at(0)); + acc = [...acc, ...data.logs.reverse()]; + } + + if (generation !== logsLoadGeneration || initialService !== $lastChosenService) { + return; + } + + allLogs = dedupeLogs(acc); + const allLogsCopy = [...allLogs]; + newLogs = allLogsCopy.splice(0, limit); + visibleLogs = allLogsCopy.splice(0, limit); + previousLogs = allLogsCopy.splice(0, limit); + + autoscroll = true; + logsFromWS = []; + } catch (e) { + console.error(e); + } finally { isSearching.set(false); isPending.set(false); - autoscroll = true; pauseWS = false; - - logsFromWS = []; } } @@ -200,6 +241,7 @@ } urlHash.set(""); + viewFlags.endDeepLink(); setTimeout(() => { setTimeout(() => { setInitialScroll(1); @@ -218,6 +260,7 @@ async function fetchIfHashIsInUrl(startWith) { const initialService = $lastChosenService; + const generation = ++logsLoadGeneration; const getLogsArray = (response) => Array.isArray(response?.logs) ? response.logs : []; @@ -255,15 +298,15 @@ const upperLogsResponse = await api.getLogs({ containerName: $lastChosenService, limit: limit - downLogs.length, - startWith: viewLogs?.at(0)[0], + startWith: logKey(viewLogs?.at(0)), hostName: $lastChosenHost, status: $chosenStatus, }); upperLogs = getLogsArray(upperLogsResponse); } } - if (initialService === $lastChosenService) { - allLogs = [...upperLogs.reverse(), ...viewLogs, ...downLogs]; + if (initialService === $lastChosenService && generation === logsLoadGeneration) { + allLogs = dedupeLogs([...upperLogs.reverse(), ...viewLogs, ...downLogs]); let allLogsCopy = [...allLogs]; @@ -294,12 +337,6 @@ } function addLogFromWS(logfromWS) { - if (isSharedLinkFocusMode) { - logsFromWS = [...logsFromWS, logfromWS]; - autoscroll = false; - return; - } - if ( (!mouseDownBlockFetch && endOffLogsIntersect) || (allLogs.length < 3 * limit && endOffLogsIntersect) @@ -321,8 +358,8 @@ previousLogs.push(logfromWS); if (allLogs.length === 3 * limit) { - allLogs = [...newLogs, ...visibleLogs, ...previousLogs]; - } else allLogs = [...allLogs, logfromWS]; + allLogs = dedupeLogs([...newLogs, ...visibleLogs, ...previousLogs]); + } else allLogs = dedupeLogs([...allLogs, logfromWS]); if (allLogs.length < 3 * limit) { } } @@ -382,7 +419,7 @@ if ( $chosenStatus && - $chosenStatus !== logfromWS[1].split(" ")[0]?.toLowerCase() + $chosenStatus !== getLogLineStatus(logfromWS[1]) ) { return; } else { @@ -419,12 +456,13 @@ function resetSearchParams() { searchText = ""; + // Also disarms any debounce timer still pending in the header, which would + // otherwise write the previous service's search term back a moment later. + searchResetVersion = searchResetVersion + 1; } - async function exitSharedLinkFocusMode(flushBufferedLogs = false) { - isSharedLinkFocusMode = false; - - if (flushBufferedLogs && logsFromWS.length) { + async function flushBufferedLogs() { + if (logsFromWS.length) { await getFullLogsSet(); logsFromWS = []; } @@ -454,35 +492,6 @@ } } - async function applySharedLinkToCurrentView(timeStamp) { - const hadSearchText = Boolean(searchText); - const hadChosenStatus = Boolean($chosenStatus); - const { hash } = applySharedLogUrl(location.href, timeStamp); - - isSharedLinkFocusMode = true; - chosenLogsString.set(timeStamp); - urlHash.set(hash); - - if (hadSearchText) { - skipNextSearchReload = true; - } - if (hadChosenStatus) { - skipNextStatusReload = true; - } - - resetSearchParams(); - searchResetVersion = searchResetVersion + 1; - refreshStatus(); - resetAllLogs(); - resetParams(); - setInitialScroll(0); - isPending.set(true); - closeWS(); - getLogsFromWS(); - topFetchIsStarted = true; - - await fetchIfHashIsInUrl(timeStamp); - } function closeWS() { if (webSocket) { webSocket.close(); @@ -509,83 +518,80 @@ initialScroll = val; } const fetchedLogs = async (doNotScroll, customStartWith) => { - if (!$isFeatching) { - stopLogsUnfetch = false; - controller = new AbortController(); - signal = controller.signal; - // if (mouseDownBlockFetch) { - // return; - // } - const initialService = $lastChosenService; - if (scrollDirection === "up") { - isFeatching.set(true); + if ($isFeatching || scrollDirection !== "up") { + return; + } - try { - let total_logs_amount = 0; - let total_logs = []; - let is_all_logs_processed = false; - let last_key = customStartWith ? customStartWith : customStartWith === 0 ? "" : allLogs.at(0)?.at(0); - while (limit < total_logs_amount && !is_all_logs_processed) { - isSearching.set(true); - const data = (await getLogs({ - containerName: $lastChosenService, - search: searchText, - limit, - status: $chosenStatus, - caseSens: !$store.caseInSensitive, - startWith: last_key, - hostName: $lastChosenHost, - signal, - })).logs.reverse(); - total_logs = [...total_logs, ...data]; - total_logs_amount += data.length; - is_all_logs_processed = data.is_end; - last_key = data.last_processed_key; - - if (initialService === $lastChosenService) { - if (data.length) { - let numberOfNewLogs = data.length; - - const logsToPrevious = visibleLogs.splice( - visibleLogs.length - numberOfNewLogs, - numberOfNewLogs - ); - - const logsToVisible = newLogs.splice( - newLogs.length - numberOfNewLogs, - numberOfNewLogs - ); - - previousLogs.splice( - previousLogs.length - numberOfNewLogs, - numberOfNewLogs - ); - newLogs = [...data, ...newLogs]; - visibleLogs = [...logsToVisible, ...visibleLogs]; - previousLogs = [...logsToPrevious, ...previousLogs]; - previousLogs.length = limit; - - allLogs = [...newLogs, ...visibleLogs, ...previousLogs]; - } - if (data.length === limit) { - setTimeout(() => { - if (!doNotScroll) { - scrollToNewLogsEnd(".newLogsEnd"); - } - }, 50); - } + stopLogsUnfetch = false; + controller = new AbortController(); + signal = controller.signal; + const initialService = $lastChosenService; + isFeatching.set(true); - } - isSearching.set(false); + try { + let total_logs_amount = 0; + let total_logs = []; + let is_all_logs_processed = false; + let last_key = customStartWith + ? customStartWith + : customStartWith === 0 + ? "" + : logKey(allLogs.at(0)); + + while (total_logs_amount < limit && !is_all_logs_processed) { + isSearching.set(true); + const response = await getLogs({ + containerName: $lastChosenService, + search: searchText, + limit, + status: $chosenStatus, + caseSens: !$store.caseInSensitive, + startWith: last_key, + hostName: $lastChosenHost, + signal, + }); + + const data = response.logs.reverse(); + total_logs = [...total_logs, ...data]; + total_logs_amount += data.length; + is_all_logs_processed = response.is_end; + last_key = response.last_processed_key; + + if (initialService !== $lastChosenService || !data.length) { + break; } - lastFetchActionIsFetch = true; - return total_logs; - } catch (e) { - console.log(e); + + const numberOfNewLogs = data.length; + const logsToPrevious = visibleLogs.splice( + visibleLogs.length - numberOfNewLogs, + numberOfNewLogs + ); + const logsToVisible = newLogs.splice( + newLogs.length - numberOfNewLogs, + numberOfNewLogs + ); + previousLogs.splice(previousLogs.length - numberOfNewLogs, numberOfNewLogs); + + newLogs = [...data, ...newLogs]; + visibleLogs = [...logsToVisible, ...visibleLogs]; + previousLogs = [...logsToPrevious, ...previousLogs].slice(0, limit); + allLogs = dedupeLogs([...newLogs, ...visibleLogs, ...previousLogs]); + + if (data.length === limit && !doNotScroll) { + setTimeout(() => { + scrollToNewLogsEnd(".newLogsEnd"); + }, 50); } } + + lastFetchActionIsFetch = true; + return total_logs; + } catch (e) { + console.log(e); + } finally { + isSearching.set(false); + isFeatching.set(false); } - isFeatching.set(false); }; const fetchedTopLogs = async (customStartWith) => { @@ -606,7 +612,11 @@ let total_logs = []; let total_received_logs_count = 0; let is_all_logs_processed = false; - let last_key = customStartWith ? customStartWith : customStartWith === 0 ? "" : allLogs.at(0)?.at(0); + let last_key = customStartWith + ? customStartWith + : customStartWith === 0 + ? "" + : logKey(allLogs.at(0)); while (limit > total_received_logs_count && !is_all_logs_processed) { isSearching.set(true); @@ -623,13 +633,22 @@ is_all_logs_processed = data.is_end; last_key = data.last_processed_key; total_received_logs_count += data.logs.length; + if (!data.logs.length) { + break; + } total_logs = [...total_logs, ...data.logs.reverse()]; } isSearching.set(false); isFeatching.set(false); if (initialService === $lastChosenService) { - if (total_logs.length === limit) { + // Nothing older left: stop asking, or the top loader repeats the same + // request every tick forever. + startOfHistoryReached = is_all_logs_processed && !total_logs.length; + + // Any rows at all, not a full page: the oldest page is almost always a + // partial one, and requiring a whole page threw the start of history away. + if (total_logs.length) { let numberOfNewLogs = total_logs.length; const logsToPrevious = visibleLogs.splice(0, numberOfNewLogs); const logsToVisible = newLogs.splice(0, numberOfNewLogs); @@ -637,7 +656,7 @@ newLogs = [...total_logs, ...newLogs]; visibleLogs = [...logsToVisible, ...visibleLogs]; previousLogs = [...logsToPrevious, ...previousLogs]; - allLogs = [...newLogs, ...visibleLogs, ...previousLogs]; + allLogs = dedupeLogs([...newLogs, ...visibleLogs, ...previousLogs]); } fetchedData = total_logs; } @@ -650,7 +669,7 @@ const initialService = $lastChosenService; isFeatching.set(true); - let last_key = allLogs.at(-1) ? allLogs.at(-1)[0] : ""; + let last_key = logKey(allLogs.at(-1)); let total_logs = []; let total_received_logs_count = 0; let is_all_logs_processed = false; @@ -669,6 +688,9 @@ total_received_logs_count += data.logs.length; is_all_logs_processed = data.is_end; last_key = data.last_processed_key; + if (!data.logs.length) { + break; + } total_logs = [...total_logs, ...data.logs]; } isSearching.set(false); @@ -682,7 +704,7 @@ newLogs = [...newLogs, ...logsToNew]; visibleLogs = [...visibleLogs, ...logsToVisible]; previousLogs = [...previousLogs, ...total_logs]; - allLogs = [...newLogs, ...visibleLogs, ...previousLogs]; + allLogs = dedupeLogs([...newLogs, ...visibleLogs, ...previousLogs]); if (total_logs.length === limit) { scrollToNewLogsEnd(".newLogsEnd", true); } @@ -696,34 +718,22 @@ } }; - // - - $: { - (async () => { - if ($lastChosenHost && $lastChosenService) { - await exitSharedLinkFocusMode(); - setInitialScroll(0); - resetAllLogs(); - resetParams(); - resetSearchParams(); - refreshStatus(); - isPending.set(true); - closeWS(); - await checkIfHashIsInUrl(); - addScrollLIstenersToLogs(); - } - })(); - } + let scrollHandler = null; + let scrollTarget = null; function addScrollLIstenersToLogs() { - let isEventOnScroll = false; + clearInterval(scrollListenerIntervalId); - const interval = setInterval(() => { + scrollListenerIntervalId = setInterval(() => { const logsContEl = document.querySelector("#logs"); if (logsContEl) { - logsContEl.addEventListener("scroll", function () { + // Without this, every reload stacked another listener on the same node. + if (scrollTarget && scrollHandler) { + scrollTarget.removeEventListener("scroll", scrollHandler); + } + scrollHandler = function () { let st = window.scrollY || logsContEl.scrollTop; if (st > lastScrollTop) { scrollDirection = "down"; @@ -739,24 +749,135 @@ pinedBadgeTimer = setTimeout(function () { pinedBadgeIsVisible = false; }, 350); - }); - isEventOnScroll = true; - } - if (isEventOnScroll) { - clearInterval(interval); - isEventOnScroll = false; + }; + scrollTarget = logsContEl; + logsContEl.addEventListener("scroll", scrollHandler); + clearInterval(scrollListenerIntervalId); } }, 1000); } - $: { + + + + + + const checkIfScrollOnTop = () => { + return setInterval(async () => { + if ( + startOfLogsIntersect && + allLogs.length >= 3 * limit && + !topFetchIsStarted && + !startOfHistoryReached + ) { + const data = await fetchedTopLogs(); + newLogsAmount = data.length; + isFeatching.set(false); + + scrollToSpecificLog(".fetchFromStart", { + behavior: "auto", + block: "start", + inline: "center", + }); + + topFetchIsStarted = false; + } + }, 500); + }; + + let topScrollIntervalId = null; + let scrollListenerIntervalId = null; + let onResize = null; + + onMount(async () => { + topScrollIntervalId = checkIfScrollOnTop(); + initialScroll = 1; + + onResize = () => { + const logsContEl = document.querySelector("#logs"); + if (logsContEl) { + // Never 0: a short pane would otherwise request no logs at all. + limit = Math.max(10, Math.round(logsContEl.offsetHeight / 200) * 10); + } + }; + window.addEventListener("resize", onResize); + }); + + onDestroy(() => { + clearInterval(topScrollIntervalId); + clearInterval(scrollListenerIntervalId); + if (scrollTarget && scrollHandler) { + scrollTarget.removeEventListener("scroll", scrollHandler); + } + clearTimeout(extremalScrollId); + clearTimeout(pinedBadgeTimer); + if (onResize) { + window.removeEventListener("resize", onResize); + } + closeWS(); + // The component is going away; it must not keep driving the shared stores + // the surviving instance reads. + logsLoadGeneration = logsLoadGeneration + 1; + isFeatching.set(false); + isSearching.set(false); + isPending.set(false); + }); + + // Reading allLogs makes this run once the new rows are in the DOM, which is + // what the scroll depends on. + $effect(() => { + allLogs; + if (autoscroll) { + div && div.scrollTo(0, div.scrollHeight ? div.scrollHeight : 0); + } + autoscroll = false; + }); + $effect.pre(() => { + if (dateIntersects.length !== allLogs.length) { + dateIntersects = Array.from( + { length: allLogs.length }, + (_, i) => dateIntersects[i] ?? false + ); + } + }); + $effect.pre(() => { + if (dateIntersects) { + findLastVisibleLog(); + } + }); + // + + $effect(() => { + (async () => { + if ($lastChosenHost && $lastChosenService) { + // Read without subscribing: referencing $urlHash here would make this + // block depend on it, and clearing the hash would retrigger it forever. + if (get(urlHash)) { + viewFlags.beginDeepLink(); + } + // Let this flush settle first: resetting synchronously re-enters this + // effect through the state it writes. + await tick(); + setInitialScroll(0); + resetAllLogs(); + resetParams(); + resetSearchParams(); + refreshStatus(); + + isPending.set(true); + closeWS(); + await checkIfHashIsInUrl(); + addScrollLIstenersToLogs(); + } + })(); + }); + $effect(() => { + const currentSearchText = searchText; (async () => { - if (skipNextSearchReload) { - skipNextSearchReload = false; + if (viewFlags.consumeSearchSkip() || viewFlags.isDeepLinkPending()) { return; } - await exitSharedLinkFocusMode(); - if (searchText) { + if (currentSearchText) { resetParams(); resetAllLogs(); isPending.set(true); @@ -767,16 +888,14 @@ } addScrollLIstenersToLogs(); })(); - } - - $: { + }); + $effect(() => { + const currentStatus = $chosenStatus; (async () => { - if (skipNextStatusReload) { - skipNextStatusReload = false; + if (viewFlags.consumeStatusSkip() || viewFlags.isDeepLinkPending()) { return; } - await exitSharedLinkFocusMode(); - if ($chosenStatus) { + if (currentStatus) { resetParams(); resetAllLogs(); isPending.set(true); @@ -787,82 +906,31 @@ } addScrollLIstenersToLogs(); })(); - } - - $: { + }); + $effect(() => { isInterceptorVIsible(intersects[0], fetchedLogs, !mouseDownBlockFetch); - } - $: { + }); + $effect(() => { isInterceptorVIsible(intersects[1], unfetchedLogs, !mouseDownBlockFetch); - } + }); // $: { // isInterceptorVIsible(intersects[2], fetchedLogs, mouseDownBlockFetch); // } - $: { + $effect(() => { isInterceptorVIsible(intersects[3], unfetchedLogs, mouseDownBlockFetch); - } - - $: { + }); + $effect(() => { if ([...allLogs]) { highlightSearchText(); } - } - - $: { + }); + $effect(() => { (async () => { - if ( - shouldFlushBufferedLogs( - logsFromWS.length, - isSharedLinkFocusMode, - false - ) && - endOffLogsIntersect - ) { - logsFromWS.length && (await getFullLogsSet()); + if (logsFromWS.length && endOffLogsIntersect) { + await getFullLogsSet(); logsFromWS = []; } })(); - } - - const checkIfScrollOnTop = () => { - const checkIfScrollOnTopInterval = setInterval(async () => { - if ( - startOfLogsIntersect && - allLogs.length >= 3 * limit && - !topFetchIsStarted - ) { - const data = await fetchedTopLogs(); - newLogsAmount = data.length; - isFeatching.set(false); - - scrollToSpecificLog(".fetchFromStart", { - behavior: "auto", - block: "start", - inline: "center", - }); - - topFetchIsStarted = false; - } - }, 500); - }; - - onMount(async () => { - checkIfScrollOnTop(); - initialScroll = 1; - - window.addEventListener("resize", () => { - const logsContEl = document.querySelector("#logs"); - if (logsContEl) { - limit = Math.round(logsContEl.offsetHeight / 200) * 10; - } - }); - }); - - afterUpdate(() => { - if (shouldAutoScrollLogs(autoscroll, isSharedLinkFocusMode)) { - div && div.scrollTo(0, div.scrollHeight ? div.scrollHeight : 0); - } - autoscroll = false; }); @@ -882,20 +950,20 @@ {#if $isPending}{:else}
- +
{#if $isSearching}
{/if} -
+
-
+
- {#each allLogs as logItem, i} + {#each allLogs as logItem, i (logKey(logItem) || i)} {#if transformLogStringForTimeBudget(logItem, $store.UTCtime) !== transformLogStringForTimeBudget(allLogs[i - 1], $store.UTCtime) && i - 1 >= 0}
@@ -920,15 +988,12 @@ ? 'chosen' : ''}" > - {#if $chosenLogsString === logItem?.at(0)} - - {/if} {#if i === limit / 2 - 1} -
+
{/if} {#if i === allLogs.length - limit / 2 && allLogs.length >= 3 * limit} @@ -936,7 +1001,7 @@ element={elements[1]} bind:intersecting={intersects[1]} > -
+
{/if} {#if i === 0 && allLogs.length >= 3 * limit} @@ -944,7 +1009,7 @@ element={elements[2]} bind:intersecting={intersects[2]} > -
+
{/if} {#if i === allLogs.length - 1 && allLogs.length >= 3 * limit} @@ -952,7 +1017,7 @@ element={elements[3]} bind:intersecting={intersects[3]} > -
+
{/if} { + // Copy only: re-pointing the view at the link resets the + // loaded logs and the websocket. + copyCustomText(nextUrl, () => { showCopiedUrlToast(); - await applySharedLinkToCurrentView(timeStamp); }); }} - getLogsByTagOptions={(limit, searchText)} />
+>
{/each} @@ -989,19 +1054,18 @@ element={endOffLogs} bind:intersecting={endOffLogsIntersect} > -
+
-
+
{#if !endOffLogsIntersect && allLogs.length}
{ - await exitSharedLinkFocusMode(true); + await flushBufferedLogs(); scrollFromButton = true; autoscroll = true; - scrollDirection === "up"; + scrollDirection = "up"; // logsFromWS.length && (await getFullLogsSet()); setTimeout(() => { @@ -1012,20 +1076,19 @@
{/if}
-
+
{/if} { + onmousedown={(e) => { mouseDownBlockFetch = true; }} - on:mouseup={(e) => { + onmouseup={(e) => { mouseDownBlockFetch = false; clearInterval(extremalScrollId); interceptorsWait = false; }} - on:keydown={(e) => { + onkeydown={(e) => { handleKeydown(e, "Escape", () => { - exitSharedLinkFocusMode(); chosenLogsString.set(""); chosenStatus.set(""); }); diff --git a/application/frontend/src/Views/Logs/NewLogsV2.test.mjs b/application/frontend/src/Views/Logs/NewLogsV2.test.mjs new file mode 100644 index 0000000..0a3b69e --- /dev/null +++ b/application/frontend/src/Views/Logs/NewLogsV2.test.mjs @@ -0,0 +1,277 @@ +import assert from "node:assert/strict"; +import { + bundleComponent, + installDom, + jsonResponse, + settle, + importBundle, + main, +} from "../../../test/harness.mjs"; + +const PAGE = [ + ["2026-02-10T12:44:03.560000000Z", "ONLOGS: Container listening started!"], + ["2026-02-10T12:44:07.370000000Z", "a"], + ["2026-02-10T12:44:07.380000000Z", "b"], +]; + +function stubFetch(counter) { + return async (url) => { + const target = String(url); + if (target.includes("getLogs?")) { + counter.getLogs += 1; + return jsonResponse({ + // The component reverses this array in place, so hand out a fresh copy. + logs: PAGE.map((row) => [...row]), + last_processed_key: PAGE[0][0], + is_end: true, + }); + } + if (target.includes("getPrevLogs?") || target.includes("getLogWithPrev?")) { + return jsonResponse({ logs: [], last_processed_key: "", is_end: true }); + } + return jsonResponse({ error: null }); + }; +} + +// A run of non-matching keys makes the backend return zero rows with +// is_end:false and last_processed_key:"", which resets the cursor to the newest +// row. The client must stop, not re-request the same empty page forever. +const RUNAWAY_CAP = 40; + +function stubEmptyPageFetch(counter) { + return async (url) => { + const target = String(url); + if (target.includes("getLogs?")) { + counter.getLogs += 1; + if (counter.getLogs > RUNAWAY_CAP) { + // Break the loop so the test reports a count instead of hanging. + return jsonResponse({ logs: [], last_processed_key: "", is_end: true }); + } + return jsonResponse({ logs: [], last_processed_key: "", is_end: false }); + } + if (target.includes("getPrevLogs?") || target.includes("getLogWithPrev?")) { + return jsonResponse({ logs: [], last_processed_key: "", is_end: true }); + } + return jsonResponse({ error: null }); + }; +} + +function stubFailingFetch(counter) { + return async (url) => { + const target = String(url); + if (target.includes("getLogs?")) { + counter.getLogs += 1; + return { status: 502, ok: false, json: async () => ({}) }; + } + return jsonResponse({ logs: [], last_processed_key: "", is_end: true }); + }; +} + +function stubOverlappingFetch(counter) { + const rows = [ + ["2026-02-10T12:44:03.560000000Z", "row-a", "2026-02-10T12:44:03.560000000Z +1-1"], + ["2026-02-10T12:44:03.561000000Z", "row-b", "2026-02-10T12:44:03.561000000Z +1-2"], + ]; + return async (url) => { + const target = String(url); + if (target.includes("getLogs?")) { + counter.getLogs += 1; + return jsonResponse({ + logs: rows.map((r) => [...r]), + last_processed_key: rows.at(-1)[2], + is_end: false, + }); + } + return jsonResponse({ logs: [], last_processed_key: "", is_end: true }); + }; +} + +function renderedRowCount(target) { + return target.querySelectorAll(".chosenString").length; +} + +function renderedTimestamps(target) { + return [...target.querySelectorAll(".time p")] + .map((el) => el.textContent.trim()) + .filter(Boolean); +} + +async function mountView(bundle, fetchImpl, counter) { + const { window } = installDom({ fetchImpl }); + const { NewLogsV2, lastChosenHost, lastChosenService, isPending } = bundle; + + lastChosenHost.set("testhost"); + lastChosenService.set("testservice"); + isPending.set(false); + + const target = window.document.body; + const component = bundle.mount(NewLogsV2, { target }); + await settle(); + return { component, target, counter }; +} + +main(async () => { + const bundlePath = await bundleComponent("test/entry.js"); + + const counter = { getLogs: 0 }; + installDom({ fetchImpl: stubFetch(counter) }); + const bundle = await importBundle(bundlePath); + + const { component, target } = await mountView(bundle, stubFetch(counter), counter); + + const rows = renderedRowCount(target); + const timestamps = renderedTimestamps(target); + + console.log(` backend returned ${PAGE.length} rows in ${counter.getLogs} request(s)`); + console.log(` component rendered ${rows} rows`); + for (const t of timestamps) console.log(` ${t}`); + + assert.equal( + rows, + PAGE.length, + `the backend returned ${PAGE.length} rows but the view rendered ${rows} ` + + `(${(rows / PAGE.length).toFixed(1)}x duplication)` + ); + + assert.equal( + new Set(timestamps).size, + timestamps.length, + `duplicate rows on screen: ${JSON.stringify(timestamps)}` + ); + + bundle.unmount(component); + + // --- an empty page must end the load, not restart it --- + const emptyCounter = { getLogs: 0 }; + const empty = await mountView( + bundle, + stubEmptyPageFetch(emptyCounter), + emptyCounter + ); + + console.log(` empty-page load issued ${emptyCounter.getLogs} request(s)`); + assert.ok( + emptyCounter.getLogs < RUNAWAY_CAP, + `an empty page with is_end:false re-requested the same page ` + + `${emptyCounter.getLogs} times; the cursor resets to the newest row and ` + + `the client never terminates` + ); + assert.equal( + renderedRowCount(empty.target), + 0, + "an empty result set should render no rows" + ); + bundle.unmount(empty.component); + + // --- a failed request must not wedge the view --- + const failingCounter = { getLogs: 0 }; + const failing = await mountView( + bundle, + stubFailingFetch(failingCounter), + failingCounter + ); + + const pending = bundle.isPending; + const searching = bundle.isSearching; + let pendingValue; + let searchingValue; + pending.subscribe((v) => (pendingValue = v))(); + searching.subscribe((v) => (searchingValue = v))(); + + console.log(` after a 502: isPending=${pendingValue} isSearching=${searchingValue}`); + assert.equal(pendingValue, false, "a failed request left the spinner up forever"); + assert.equal(searchingValue, false, "a failed request left the loader up forever"); + bundle.unmount(failing.component); + + // --- destroying the view must not leave a zombie driving the shared stores --- + const zombieCounter = { getLogs: 0 }; + const { window: zombieWindow, sockets } = installDom({ + fetchImpl: stubFetch(zombieCounter), + }); + bundle.lastChosenHost.set("testhost"); + bundle.lastChosenService.set("testservice"); + bundle.isPending.set(false); + const zombie = bundle.mount(bundle.NewLogsV2, { target: zombieWindow.document.body }); + await settle(); + + assert.ok(sockets.length > 0, "the view never opened a websocket"); + bundle.unmount(zombie); + await settle(5); + + assert.ok( + sockets.every((s) => s.readyState === 3), + "destroying the view left its websocket open" + ); + + let stillFetching; + bundle.isFeatching.subscribe((v) => (stillFetching = v))(); + assert.equal( + stillFetching, + false, + "a destroyed view left the shared isFeatching store set, which blocks the live one" + ); + + // --- a re-served row must not reach the screen twice --- + const overlapCounter = { getLogs: 0 }; + const overlap = await mountView( + bundle, + stubOverlappingFetch(overlapCounter), + overlapCounter + ); + const overlapMessages = [...overlap.target.querySelectorAll(".message p")] + .map((el) => el.textContent.trim()) + .filter((t) => t.startsWith("row-")); + + console.log(` overlapping pages rendered: ${JSON.stringify(overlapMessages)}`); + assert.equal( + new Set(overlapMessages).size, + overlapMessages.length, + `a re-served row reached the screen twice: ${JSON.stringify(overlapMessages)}` + ); + bundle.unmount(overlap.component); + + // --- a status filter must not silently freeze the live tail --- + const wsCounter = { getLogs: 0 }; + const { window: wsWindow, sockets: wsSockets } = installDom({ + fetchImpl: stubFetch(wsCounter), + }); + bundle.lastChosenHost.set("testhost"); + bundle.lastChosenService.set("testservice"); + bundle.isPending.set(false); + const filtered = bundle.mount(bundle.NewLogsV2, { target: wsWindow.document.body }); + await settle(); + + bundle.chosenStatus.set("warn"); + await settle(5); + + const socket = wsSockets.at(-1); + assert.ok(socket, "no websocket was opened"); + + // Nothing sets endOffLogsIntersect under jsdom, so a delivered line lands in + // the buffer and shows on the scroll-to-bottom badge. + const bufferedCount = () => { + const badge = wsWindow.document.querySelector(".buttonToBottomNumber p"); + return badge ? Number(badge.textContent.trim()) : 0; + }; + + // A line the shared classifier calls "warn", not a bare leading token. + socket.onmessage({ + data: JSON.stringify([ + "2026-02-10T12:44:09.000000000Z", + "2026-02-10 WARNING disk almost full", + "2026-02-10T12:44:09.000000000Z +9-9", + ]), + }); + await settle(5); + + const delivered = bufferedCount(); + console.log(` live warn line with a "warn" filter delivered: ${delivered > 0}`); + assert.ok( + delivered > 0, + "a live line the classifier calls warn was dropped while the warn filter was active" + ); + bundle.chosenStatus.set(""); + bundle.unmount(filtered); + + console.log("NewLogsV2 duplication tests passed"); +}); diff --git a/application/frontend/src/Views/Logs/Spiner.svelte b/application/frontend/src/Views/Logs/Spiner.svelte index 347cb7f..a71cf07 100644 --- a/application/frontend/src/Views/Logs/Spiner.svelte +++ b/application/frontend/src/Views/Logs/Spiner.svelte @@ -1,12 +1,7 @@
diff --git a/application/frontend/src/Views/Logs/classifier.test.mjs b/application/frontend/src/Views/Logs/classifier.test.mjs new file mode 100644 index 0000000..e962f2c --- /dev/null +++ b/application/frontend/src/Views/Logs/classifier.test.mjs @@ -0,0 +1,52 @@ +// Shared with backend/app/containerdb/classifier_test.go: both implementations +// must agree on every one of these. +import assert from "node:assert/strict"; +import { + bundleComponent, + installDom, + importBundle, +} from "../../../test/harness.mjs"; + +installDom({}); +const { classifyLogLine, getLogLineStatus } = await importBundle( + await bundleComponent("test/entry.js") +); + +const ESC = ""; + +const CASES = [ + ["ERROR something failed", "error"], + ["Error: connection refused", "error"], + ["error: connection refused", "error"], + ["ERR disk full", "error"], + ["WARN low memory", "warn"], + ["WARNING low memory", "warn"], + ["warning low memory", "warn"], + ["DEBUG entering loop", "debug"], + ["debug entering loop", "debug"], + ["INFO started", "info"], + ["INFO ERROR_COUNT=0", "info"], + ["ONLOGS: Container listening started!", "meta"], + ["plain application output", "other"], + ["", "other"], + [`${ESC}[31mERROR${ESC}[0m red text`, "error"], + ["the word information appears here", "info"], + ["2026-02-10 INFO ready", "info"], +]; + +function run() { + for (const [line, expected] of CASES) { + assert.equal( + classifyLogLine(line), + expected, + `classifyLogLine(${JSON.stringify(line)}) should be ${expected}` + ); + } + + assert.equal(getLogLineStatus("plain application output"), ""); + assert.equal(getLogLineStatus("ERROR boom"), "error"); + + console.log("log level classifier tests passed"); +} + +run(); diff --git a/application/frontend/src/Views/Logs/functions.js b/application/frontend/src/Views/Logs/functions.js index feb9bf2..d9c9dbd 100644 --- a/application/frontend/src/Views/Logs/functions.js +++ b/application/frontend/src/Views/Logs/functions.js @@ -5,92 +5,78 @@ export { findSearchTextInLogs }; const api = new FetchApi(); -export const timezoneOffsetSec = new Date().getTimezoneOffset() * 60; - -export const getLogLineStatus = (logLine = "") => { - const normalizedLogLine = stripAnsi(logLine); - const statuses_errors = ["ERROR", "ERR", "Error", "Err", "error"]; - const statuses_warnings = ["WARN", "WARNING", "warning"]; - const statuses_other = ["DEBUG", "INFO", "ONLOGS", "debug", "info", "onlogs"]; - const logLineItems = normalizedLogLine.split(" "); - var i, j; - - for (i = 0; i < logLineItems.length; i++) { - for (j = 0; j < statuses_errors.length; j++) { - if (logLineItems[i].includes(statuses_errors[j])) { - return "error"; - } - } - for (j = 0; j < statuses_warnings.length; j++) { - if (logLineItems[i].includes(statuses_warnings[j])) { - return "warn"; - } - } - for (j = 0; j < statuses_other.length; j++) { - if (logLineItems[i].includes(statuses_other[j])) { - return statuses_other[j].toLowerCase() === "onlogs" - ? "meta" - : statuses_other[j].toLowerCase(); +// One classification rule, mirrored by containerdb.GetLogStatusKey in Go. +const LEVELS = [ + ["ERROR", "error"], + ["ERR", "error"], + ["WARNING", "warn"], + ["WARN", "warn"], + ["DEBUG", "debug"], + ["INFO", "info"], + ["ONLOGS", "meta"], +]; + +export const classifyLogLine = (logLine = "") => { + for (const token of stripAnsi(String(logLine)).split(/\s+/)) { + const upper = token.toUpperCase(); + for (const [needle, level] of LEVELS) { + if (upper.includes(needle)) { + return level; } } } - return ""; + return "other"; }; -export const transformLogString = (t, options) => { - return options - ? new Date( - new Date().setTime( - new Date(t?.at(0)?.slice(0, 22)?.replace("T", " "))?.getTime() - ) - ) - .toLocaleString("sv-EN", { - hour: "2-digit", - minute: "2-digit", - second: "2-digit", - fractionalSecondDigits: 3, - }) - .replace(",", ".") - : new Date( - new Date().setTime( - new Date(t?.at(0)?.slice(0, 19)?.replace("T", " "))?.getTime() - - timezoneOffsetSec * 1000 - ) - ) - .toLocaleString("sv-EN", { - hour: "2-digit", - minute: "2-digit", - second: "2-digit", - fractionalSecondDigits: 3, - }) - .replace(",", "."); +// The badge is hidden for unclassified lines, so "other" is reported as "". +export const getLogLineStatus = (logLine = "") => { + const level = classifyLogLine(logLine); + return level === "other" ? "" : level; }; -export const transformLogStringForTimeBudget = (t, options) => { - return options - ? new Date( - new Date().setTime( - new Date(t?.at(0)?.slice(0, 22)?.replace("T", " "))?.getTime() - ) - ) - .toLocaleString("en-US", { - month: "short", - day: "2-digit", - year: "numeric", - }) - .replace(",", "") - : new Date( - new Date().setTime( - new Date(t?.at(0)?.slice(0, 19)?.replace("T", " "))?.getTime() - - timezoneOffsetSec * 1000 - ) - ) - .toLocaleString("en-US", { - month: "short", - day: "2-digit", - year: "numeric", - }) - .replace(",", ""); +// Milliseconds are what distinguish two adjacent rows, so they must survive; and +// the zone offset has to come from the timestamp itself, not from module-load +// time, or anything across a DST boundary is an hour out. +const parseLogTime = (t) => { + const raw = t?.at?.(0); + if (!raw) { + return null; + } + const date = new Date(raw); + return Number.isNaN(date.getTime()) ? null : date; +}; + +const zoneOf = (utc) => (utc ? "UTC" : undefined); + +export const transformLogString = (t, utc) => { + const date = parseLogTime(t); + if (!date) { + return ""; + } + return date + .toLocaleString("sv-SE", { + timeZone: zoneOf(utc), + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + fractionalSecondDigits: 3, + }) + .replace(",", "."); +}; + +export const transformLogStringForTimeBudget = (t, utc) => { + const date = parseLogTime(t); + if (!date) { + return ""; + } + return date + .toLocaleString("en-US", { + timeZone: zoneOf(utc), + month: "short", + day: "2-digit", + year: "numeric", + }) + .replace(",", ""); }; export const getLogs = async function ({ @@ -165,20 +151,6 @@ export const scrollToNewLogsEnd = (selector, alignToTop) => { } }; -export const checkLastLogTimeStamp = (lastTimeStamp, newTimestamp) => { - const timestamp = new Date(newTimestamp).getTime() - 1; - if (lastTimeStamp > timestamp) { - return timestamp; - } -}; - -export const forceToBottom = () => { - const logsContainerEl = document.querySelector("#logs"); - if (logsContainerEl) { - logsContainerEl.scrollTop = logsContainerEl.scrollHeight; - } -}; - export const scrollToSpecificLog = (selector, position) => { const el = document.querySelector(selector); diff --git a/application/frontend/src/Views/Logs/shareLink.js b/application/frontend/src/Views/Logs/shareLink.js index 98eb8de..a7aba5e 100644 --- a/application/frontend/src/Views/Logs/shareLink.js +++ b/application/frontend/src/Views/Logs/shareLink.js @@ -10,18 +10,3 @@ export const buildSharedLogUrl = (currentHref = "", timestamp = "") => { const [baseUrl] = String(currentHref).split("#"); return `${baseUrl}${getSharedLogHash(timestamp)}`; }; - -export const applySharedLogUrl = ( - currentHref = "", - timestamp = "", - historyLike = window.history -) => { - const nextUrl = buildSharedLogUrl(currentHref, timestamp); - - historyLike.replaceState(null, "", nextUrl); - - return { - nextUrl, - hash: getSharedLogHash(timestamp), - }; -}; diff --git a/application/frontend/src/Views/Logs/shareLink.test.mjs b/application/frontend/src/Views/Logs/shareLink.test.mjs index 132bdfa..174f638 100644 --- a/application/frontend/src/Views/Logs/shareLink.test.mjs +++ b/application/frontend/src/Views/Logs/shareLink.test.mjs @@ -1,9 +1,5 @@ import assert from "node:assert/strict"; -import { - applySharedLogUrl, - buildSharedLogUrl, - getSharedLogHash, -} from "./shareLink.js"; +import { buildSharedLogUrl, getSharedLogHash } from "./shareLink.js"; const timestamp = "2026-03-09T08:00:00.123456789Z"; @@ -33,26 +29,4 @@ assert.equal( `http://localhost:5173/view/host/service#${timestamp}` ); -const historyCalls = []; -const historyMock = { - replaceState(...args) { - historyCalls.push(args); - }, -}; - -const result = applySharedLogUrl( - "http://localhost:5173/view/host/service#stale", - timestamp, - historyMock -); - -assert.deepEqual(result, { - nextUrl: `http://localhost:5173/view/host/service#${timestamp}`, - hash: `#${timestamp}`, -}); - -assert.deepEqual(historyCalls, [ - [null, "", `http://localhost:5173/view/host/service#${timestamp}`], -]); - console.log("share link tests passed"); diff --git a/application/frontend/src/Views/Logs/shareLinkViewState.js b/application/frontend/src/Views/Logs/shareLinkViewState.js index fbbea65..eb8d4f7 100644 --- a/application/frontend/src/Views/Logs/shareLinkViewState.js +++ b/application/frontend/src/Views/Logs/shareLinkViewState.js @@ -3,13 +3,37 @@ export const hasSearchResetRequest = ( nextResetVersion = 0 ) => nextResetVersion !== lastResetVersion; -export const shouldAutoScrollLogs = ( - autoscroll = false, - isSharedLinkFocusMode = false -) => autoscroll && !isSharedLinkFocusMode; +// Svelte invalidates an object when any of its members is assigned, so plain +// fields cannot carry state between reactive blocks without retriggering them. +// Closure variables behind function calls can. +export function createLogsViewFlags() { + let deepLinkPending = false; + let skipSearchReload = false; + let skipStatusReload = false; -export const shouldFlushBufferedLogs = ( - logsFromWSLength = 0, - isSharedLinkFocusMode = false, - releaseRequested = false -) => logsFromWSLength > 0 && (!isSharedLinkFocusMode || releaseRequested); + return { + beginDeepLink() { + deepLinkPending = true; + // The reset of searchText/chosenStatus that follows retriggers the search + // and status blocks; that reload must not overwrite the deep-link window. + skipSearchReload = true; + skipStatusReload = true; + }, + endDeepLink() { + deepLinkPending = false; + }, + isDeepLinkPending() { + return deepLinkPending; + }, + consumeSearchSkip() { + const skip = skipSearchReload; + skipSearchReload = false; + return skip; + }, + consumeStatusSkip() { + const skip = skipStatusReload; + skipStatusReload = false; + return skip; + }, + }; +} diff --git a/application/frontend/src/Views/Logs/shareLinkViewState.test.mjs b/application/frontend/src/Views/Logs/shareLinkViewState.test.mjs index 961faa3..398d541 100644 --- a/application/frontend/src/Views/Logs/shareLinkViewState.test.mjs +++ b/application/frontend/src/Views/Logs/shareLinkViewState.test.mjs @@ -1,21 +1,34 @@ import assert from "node:assert/strict"; import { hasSearchResetRequest, - shouldAutoScrollLogs, - shouldFlushBufferedLogs, + createLogsViewFlags, } from "./shareLinkViewState.js"; +// Live: LogsViewHeder disarms its pending debounce when the version bumps. assert.equal(hasSearchResetRequest(0, 0), false); assert.equal(hasSearchResetRequest(0, 1), true); assert.equal(hasSearchResetRequest(3, 4), true); -assert.equal(shouldAutoScrollLogs(true, false), true); -assert.equal(shouldAutoScrollLogs(true, true), false); -assert.equal(shouldAutoScrollLogs(false, false), false); +const flags = createLogsViewFlags(); +assert.equal(flags.isDeepLinkPending(), false); +assert.equal(flags.consumeSearchSkip(), false); +assert.equal(flags.consumeStatusSkip(), false); -assert.equal(shouldFlushBufferedLogs(0, false, false), false); -assert.equal(shouldFlushBufferedLogs(5, false, false), true); -assert.equal(shouldFlushBufferedLogs(5, true, false), false); -assert.equal(shouldFlushBufferedLogs(5, true, true), true); +flags.beginDeepLink(); +assert.equal(flags.isDeepLinkPending(), true); +// One skip each: the search and status blocks retrigger once after the reset. +assert.equal(flags.consumeSearchSkip(), true); +assert.equal(flags.consumeSearchSkip(), false); +assert.equal(flags.consumeStatusSkip(), true); +assert.equal(flags.consumeStatusSkip(), false); + +assert.equal(flags.isDeepLinkPending(), true); +flags.endDeepLink(); +assert.equal(flags.isDeepLinkPending(), false); + +const other = createLogsViewFlags(); +flags.beginDeepLink(); +assert.equal(other.isDeepLinkPending(), false); +assert.equal(other.consumeSearchSkip(), false); console.log("share link view state tests passed"); diff --git a/application/frontend/src/Views/Logs/timestamps.test.mjs b/application/frontend/src/Views/Logs/timestamps.test.mjs new file mode 100644 index 0000000..26a1f13 --- /dev/null +++ b/application/frontend/src/Views/Logs/timestamps.test.mjs @@ -0,0 +1,60 @@ +process.env.TZ = "Europe/Kyiv"; + +import assert from "node:assert/strict"; +import { + bundleComponent, + installDom, + importBundle, +} from "../../../test/harness.mjs"; + +installDom({}); +const { transformLogString, transformLogStringForTimeBudget } = + await importBundle(await bundleComponent("test/entry.js")); + +const row = (ts) => [ts, "a message", ts + " +1-1"]; + +function run() { + const summer = "2026-07-15T12:44:03.567891234Z"; + const winter = "2026-01-15T12:44:03.567891234Z"; + + // Milliseconds must survive: without them, two distinct rows look identical + // and a genuine duplicate is indistinguishable from two adjacent lines. + assert.equal( + transformLogString(row(summer), true), + "12:44:03.567", + "UTC mode truncates the millisecond" + ); + assert.equal( + transformLogString(row(summer), false), + "15:44:03.567", + "local mode loses the millisecond" + ); + + const a = transformLogString(row("2026-07-15T12:44:03.560000000Z"), false); + const b = transformLogString(row("2026-07-15T12:44:03.561000000Z"), false); + assert.notEqual(a, b, `rows 1ms apart render identically: ${a} == ${b}`); + + // Europe/Kyiv is UTC+3 in July and UTC+2 in January. A single offset captured + // at module load makes everything across a DST boundary an hour wrong. + assert.equal( + transformLogString(row(winter), false), + "14:44:03.567", + "the timezone offset is not computed per timestamp" + ); + + assert.equal(transformLogStringForTimeBudget(row(summer), true), "Jul 15 2026"); + assert.equal(transformLogStringForTimeBudget(row(winter), false), "Jan 15 2026"); + + // A date that falls on the previous day in UTC but the next locally. + const lateEvening = "2026-07-15T22:30:00.000000000Z"; + assert.equal(transformLogStringForTimeBudget(row(lateEvening), true), "Jul 15 2026"); + assert.equal(transformLogStringForTimeBudget(row(lateEvening), false), "Jul 16 2026"); + + assert.equal(transformLogString(undefined, true), ""); + assert.equal(transformLogString(["not a date", "m"], true), ""); + assert.equal(transformLogStringForTimeBudget(undefined, true), ""); + + console.log("timestamp rendering tests passed"); +} + +run(); diff --git a/application/frontend/src/Views/Main/Main.svelte b/application/frontend/src/Views/Main/Main.svelte index 861337f..3503f91 100644 --- a/application/frontend/src/Views/Main/Main.svelte +++ b/application/frontend/src/Views/Main/Main.svelte @@ -1,7 +1,6 @@ diff --git a/application/frontend/src/Views/ServiceSettings/Acess.svelte b/application/frontend/src/Views/ServiceSettings/Acess.svelte deleted file mode 100644 index e69de29..0000000 diff --git a/application/frontend/src/Views/ServiceSettings/ServiceSettings.svelte b/application/frontend/src/Views/ServiceSettings/ServiceSettings.svelte index 4349f60..da366ba 100644 --- a/application/frontend/src/Views/ServiceSettings/ServiceSettings.svelte +++ b/application/frontend/src/Views/ServiceSettings/ServiceSettings.svelte @@ -1,6 +1,5 @@ @@ -8,7 +7,4 @@ {#if $lastChosenSetting.trim() === "General"} {/if} - {#if $lastChosenSetting.trim() === "Acess"} - - {/if}
diff --git a/application/frontend/src/Views/ServiceSettings/ServiceSettingsLeft.svelte b/application/frontend/src/Views/ServiceSettings/ServiceSettingsLeft.svelte deleted file mode 100644 index 2b75d9b..0000000 --- a/application/frontend/src/Views/ServiceSettings/ServiceSettingsLeft.svelte +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/application/frontend/src/assets/res/font/ChartFilled.svg b/application/frontend/src/assets/res/font/ChartFilled.svg new file mode 100644 index 0000000..5214b08 --- /dev/null +++ b/application/frontend/src/assets/res/font/ChartFilled.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/application/frontend/src/assets/res/font/WheelFilled.svg b/application/frontend/src/assets/res/font/WheelFilled.svg new file mode 100644 index 0000000..5a8d94c --- /dev/null +++ b/application/frontend/src/assets/res/font/WheelFilled.svg @@ -0,0 +1,3 @@ + + + diff --git a/application/frontend/src/assets/res/onLogsFont.css b/application/frontend/src/assets/res/onLogsFont.css index f470f14..e638d47 100644 --- a/application/frontend/src/assets/res/onLogsFont.css +++ b/application/frontend/src/assets/res/onLogsFont.css @@ -1,10 +1,10 @@ @font-face { font-family: "onLogsFont"; - src: url("onLogsFont.eot?b1b1fa2c569a9742068bfa91c7006c7a?#iefix") format("embedded-opentype"), -url("onLogsFont.woff2?b1b1fa2c569a9742068bfa91c7006c7a") format("woff2"), -url("onLogsFont.woff?b1b1fa2c569a9742068bfa91c7006c7a") format("woff"), -url("onLogsFont.ttf?b1b1fa2c569a9742068bfa91c7006c7a") format("truetype"), -url("onLogsFont.svg?b1b1fa2c569a9742068bfa91c7006c7a#onLogsFont") format("svg"); + src: url("onLogsFont.eot?aef3930177b47eac3029189d876a7102?#iefix") format("embedded-opentype"), +url("onLogsFont.woff2?aef3930177b47eac3029189d876a7102") format("woff2"), +url("onLogsFont.woff?aef3930177b47eac3029189d876a7102") format("woff"), +url("onLogsFont.ttf?aef3930177b47eac3029189d876a7102") format("truetype"), +url("onLogsFont.svg?aef3930177b47eac3029189d876a7102#onLogsFont") format("svg"); font-weight: normal; font-style: normal; } @@ -41,111 +41,117 @@ url("onLogsFont.svg?b1b1fa2c569a9742068bfa91c7006c7a#onLogsFont") format("svg"); .log-Chart:before { content: "\f106"; } -.log-Clean:before { +.log-ChartFilled:before { content: "\f107"; } -.log-Clock:before { +.log-Clean:before { content: "\f108"; } -.log-Close:before { +.log-Clock:before { content: "\f109"; } -.log-Colums:before { +.log-Close:before { content: "\f10a"; } -.log-Combine:before { +.log-Colums:before { content: "\f10b"; } -.log-Copy:before { +.log-Combine:before { content: "\f10c"; } -.log-Cut:before { +.log-Copy:before { content: "\f10d"; } -.log-Data:before { +.log-Cut:before { content: "\f10e"; } -.log-Down:before { +.log-Data:before { content: "\f10f"; } -.log-EmptyHeart:before { +.log-Down:before { content: "\f110"; } -.log-Error:before { +.log-EmptyHeart:before { content: "\f111"; } -.log-Eye:before { +.log-Error:before { content: "\f112"; } -.log-Filter:before { +.log-Eye:before { content: "\f113"; } -.log-Group:before { +.log-Filter:before { content: "\f114"; } -.log-Heart:before { +.log-Group:before { content: "\f115"; } -.log-Home:before { +.log-Heart:before { content: "\f116"; } -.log-Info:before { +.log-Home:before { content: "\f117"; } -.log-Json:before { +.log-Info:before { content: "\f118"; } -.log-Last:before { +.log-Json:before { content: "\f119"; } -.log-Leters:before { +.log-Last:before { content: "\f11a"; } -.log-Logout:before { +.log-Leters:before { content: "\f11b"; } -.log-Moon:before { +.log-Logout:before { content: "\f11c"; } -.log-Pencil:before { +.log-Moon:before { content: "\f11d"; } -.log-Plus:before { +.log-Pencil:before { content: "\f11e"; } -.log-Pointer:before { +.log-Plus:before { content: "\f11f"; } -.log-Refresh:before { +.log-Pointer:before { content: "\f120"; } -.log-Search:before { +.log-Refresh:before { content: "\f121"; } -.log-Server:before { +.log-Search:before { content: "\f122"; } -.log-Share:before { +.log-Server:before { content: "\f123"; } -.log-ShareLink:before { +.log-Share:before { content: "\f124"; } -.log-Success:before { +.log-ShareLink:before { content: "\f125"; } -.log-Sun:before { +.log-Success:before { content: "\f126"; } -.log-Tips:before { +.log-Sun:before { content: "\f127"; } -.log-User:before { +.log-Tips:before { content: "\f128"; } -.log-Warning:before { +.log-User:before { content: "\f129"; } -.log-Wheel:before { +.log-Warning:before { content: "\f12a"; } +.log-Wheel:before { + content: "\f12b"; +} +.log-WheelFilled:before { + content: "\f12c"; +} diff --git a/application/frontend/src/assets/res/onLogsFont.eot b/application/frontend/src/assets/res/onLogsFont.eot index 71e56cd..6d929b5 100644 Binary files a/application/frontend/src/assets/res/onLogsFont.eot and b/application/frontend/src/assets/res/onLogsFont.eot differ diff --git a/application/frontend/src/assets/res/onLogsFont.html b/application/frontend/src/assets/res/onLogsFont.html index 0a31b7c..05490eb 100644 --- a/application/frontend/src/assets/res/onLogsFont.html +++ b/application/frontend/src/assets/res/onLogsFont.html @@ -27,11 +27,11 @@ @font-face { font-family: "onLogsFont"; - src: url("onLogsFont.eot?c232b5525b4a4aa66122680a449abb8b?#iefix") format("embedded-opentype"), -url("onLogsFont.woff2?c232b5525b4a4aa66122680a449abb8b") format("woff2"), -url("onLogsFont.woff?c232b5525b4a4aa66122680a449abb8b") format("woff"), -url("onLogsFont.ttf?c232b5525b4a4aa66122680a449abb8b") format("truetype"), -url("onLogsFont.svg?c232b5525b4a4aa66122680a449abb8b#onLogsFont") format("svg"); + src: url("onLogsFont.eot?e3b57457eb8a115c13fe71e7061e17ca?#iefix") format("embedded-opentype"), +url("onLogsFont.woff2?e3b57457eb8a115c13fe71e7061e17ca") format("woff2"), +url("onLogsFont.woff?e3b57457eb8a115c13fe71e7061e17ca") format("woff"), +url("onLogsFont.ttf?e3b57457eb8a115c13fe71e7061e17ca") format("truetype"), +url("onLogsFont.svg?e3b57457eb8a115c13fe71e7061e17ca#onLogsFont") format("svg"); font-weight: normal; font-style: normal; } @@ -68,114 +68,120 @@ .log-Chart:before { content: "\f106"; } -.log-Clean:before { +.log-ChartFilled:before { content: "\f107"; } -.log-Clock:before { +.log-Clean:before { content: "\f108"; } -.log-Close:before { +.log-Clock:before { content: "\f109"; } -.log-Colums:before { +.log-Close:before { content: "\f10a"; } -.log-Combine:before { +.log-Colums:before { content: "\f10b"; } -.log-Copy:before { +.log-Combine:before { content: "\f10c"; } -.log-Cut:before { +.log-Copy:before { content: "\f10d"; } -.log-Data:before { +.log-Cut:before { content: "\f10e"; } -.log-Down:before { +.log-Data:before { content: "\f10f"; } -.log-EmptyHeart:before { +.log-Down:before { content: "\f110"; } -.log-Error:before { +.log-EmptyHeart:before { content: "\f111"; } -.log-Eye:before { +.log-Error:before { content: "\f112"; } -.log-Filter:before { +.log-Eye:before { content: "\f113"; } -.log-Group:before { +.log-Filter:before { content: "\f114"; } -.log-Heart:before { +.log-Group:before { content: "\f115"; } -.log-Home:before { +.log-Heart:before { content: "\f116"; } -.log-Info:before { +.log-Home:before { content: "\f117"; } -.log-Json:before { +.log-Info:before { content: "\f118"; } -.log-Last:before { +.log-Json:before { content: "\f119"; } -.log-Leters:before { +.log-Last:before { content: "\f11a"; } -.log-Logout:before { +.log-Leters:before { content: "\f11b"; } -.log-Moon:before { +.log-Logout:before { content: "\f11c"; } -.log-Pencil:before { +.log-Moon:before { content: "\f11d"; } -.log-Plus:before { +.log-Pencil:before { content: "\f11e"; } -.log-Pointer:before { +.log-Plus:before { content: "\f11f"; } -.log-Refresh:before { +.log-Pointer:before { content: "\f120"; } -.log-Search:before { +.log-Refresh:before { content: "\f121"; } -.log-Server:before { +.log-Search:before { content: "\f122"; } -.log-Share:before { +.log-Server:before { content: "\f123"; } -.log-ShareLink:before { +.log-Share:before { content: "\f124"; } -.log-Success:before { +.log-ShareLink:before { content: "\f125"; } -.log-Sun:before { +.log-Success:before { content: "\f126"; } -.log-Tips:before { +.log-Sun:before { content: "\f127"; } -.log-User:before { +.log-Tips:before { content: "\f128"; } -.log-Warning:before { +.log-User:before { content: "\f129"; } -.log-Wheel:before { +.log-Warning:before { content: "\f12a"; } +.log-Wheel:before { + content: "\f12b"; +} +.log-WheelFilled:before { + content: "\f12c"; +} @@ -217,6 +223,12 @@

onLogsFont

Chart
+
+ + + + ChartFilled +
@@ -433,5 +445,11 @@

onLogsFont

Wheel
+
+ + + + WheelFilled +
diff --git a/application/frontend/src/assets/res/onLogsFont.svg b/application/frontend/src/assets/res/onLogsFont.svg index 58a96f3..03593ea 100644 --- a/application/frontend/src/assets/res/onLogsFont.svg +++ b/application/frontend/src/assets/res/onLogsFont.svg @@ -43,222 +43,234 @@ - + + + + diff --git a/application/frontend/src/assets/res/onLogsFont.ttf b/application/frontend/src/assets/res/onLogsFont.ttf index dc9492a..e86213a 100644 Binary files a/application/frontend/src/assets/res/onLogsFont.ttf and b/application/frontend/src/assets/res/onLogsFont.ttf differ diff --git a/application/frontend/src/assets/res/onLogsFont.woff b/application/frontend/src/assets/res/onLogsFont.woff index 33875db..41ff239 100644 Binary files a/application/frontend/src/assets/res/onLogsFont.woff and b/application/frontend/src/assets/res/onLogsFont.woff differ diff --git a/application/frontend/src/assets/res/onLogsFont.woff2 b/application/frontend/src/assets/res/onLogsFont.woff2 index 60309d5..c93396f 100644 Binary files a/application/frontend/src/assets/res/onLogsFont.woff2 and b/application/frontend/src/assets/res/onLogsFont.woff2 differ diff --git a/application/frontend/src/lib/Button/Button.stories.js b/application/frontend/src/lib/Button/Button.stories.js deleted file mode 100644 index 80510b0..0000000 --- a/application/frontend/src/lib/Button/Button.stories.js +++ /dev/null @@ -1,39 +0,0 @@ -// @ts-ignore -import Button from "./Button.svelte"; -import { action } from "@storybook/addon-actions"; -import "../../assets/res/onLogsFont.css"; - -export const actionsData = { - onCkickButton: action("onClickButton"), -}; - -export default { - component: Button, - title: "Button", - excludeStories: /.*Data$/, - //πŸ‘‡ The argTypes are included so that they are properly displayed in the Actions Panel - argTypes: { - onCkickButton: { action: "onClickButton" }, - }, -}; - -const Template = ({ onCkickButton, ...args }) => ({ - Component: Button, - props: args, - on: { - ...actionsData, - }, -}); - -export const Default = Template.bind({}); -Default.args = { - title: "Text", - border: true, - highlighted: false, - minWidth: 90, - minHeight: 32, - icon: "", - state: "BUTTON_TEXT", - iconHeight: 12, - -}; diff --git a/application/frontend/src/lib/Button/Button.svelte b/application/frontend/src/lib/Button/Button.svelte index 6102e49..aa1e4fb 100644 --- a/application/frontend/src/lib/Button/Button.svelte +++ b/application/frontend/src/lib/Button/Button.svelte @@ -1,29 +1,23 @@
diff --git a/application/frontend/src/lib/ButtonToBottom/ButtonToBottom.svelte b/application/frontend/src/lib/ButtonToBottom/ButtonToBottom.svelte index eda3843..81e5669 100644 --- a/application/frontend/src/lib/ButtonToBottom/ButtonToBottom.svelte +++ b/application/frontend/src/lib/ButtonToBottom/ButtonToBottom.svelte @@ -1,18 +1,15 @@
{ + onclick={async () => { await callBack(); }} >
- +
{#if number}

{number}

diff --git a/application/frontend/src/lib/ChartMenu/Chart.svelte b/application/frontend/src/lib/ChartMenu/Chart.svelte index b4f13ae..9f6780e 100644 --- a/application/frontend/src/lib/ChartMenu/Chart.svelte +++ b/application/frontend/src/lib/ChartMenu/Chart.svelte @@ -1,194 +1,94 @@ -
- {#if data} {/if} +
+ {#if total === 0} +

No statistics recorded for this period yet

+ {:else} + + {/if}
diff --git a/application/frontend/src/lib/ChartMenu/ChartMenu.scss b/application/frontend/src/lib/ChartMenu/ChartMenu.scss index c0e0a09..e3fa033 100644 --- a/application/frontend/src/lib/ChartMenu/ChartMenu.scss +++ b/application/frontend/src/lib/ChartMenu/ChartMenu.scss @@ -1,26 +1,85 @@ -.chartHeader { - ul { - margin-top: 12px; - // gap: 6px; +.chartContainer { + display: flex; + flex-direction: column; + height: 100%; + gap: 20px; + + .chartHeader { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; + padding-bottom: 16px; + border-bottom: 1px solid $lines-color; + + @include for-mobile { + flex-direction: column; + gap: 8px; + } + } + + .chartTittle { + font-size: $main-font-l; + line-height: 1.2; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .chartSubtitle { + margin-top: 4px; + font-size: $main-font-s; + color: $text-placeholder-color; + font-variant-numeric: tabular-nums; + } + + .timeSpan { + gap: 4px; + flex-shrink: 0; + font-size: $main-font-s; + + & div { + padding: 4px 12px; + border-radius: 100px; + font-weight: 600; + cursor: pointer; + color: $text-placeholder-color; + + &:hover { + color: $text-dark-color; + } + &.active { + color: $text-onactive-color; + background-color: $active-color; + } + } } - .item { + .chartCanvas { flex: 1; + min-height: 320px; + display: flex; + align-items: center; + justify-content: center; + } + + .chartEmpty { font-size: $main-font-m; - box-shadow: $main-shadow-dark; + color: $text-placeholder-color; + } +} - cursor: pointer; - &.isActive { - color: $active-color; - } - &:first-child { - border-top-left-radius: $main-border-radius; - border-bottom-left-radius: $main-border-radius; +.dark-mode .chartContainer { + .chartHeader { + border-bottom-color: $lines-color-dark; + } + .timeSpan div { + &:hover { + color: $text-dark-color-dark; } - &:last-child { - border-top-right-radius: $main-border-radius; - border-bottom-right-radius: $main-border-radius; + &.active { + color: $text-onactive-color-dark; + background-color: $active-color-dark; } - // border-radius: $main-border-radius; } } diff --git a/application/frontend/src/lib/ChartMenu/MainChartMenu.svelte b/application/frontend/src/lib/ChartMenu/MainChartMenu.svelte index 32b899c..3ed9400 100644 --- a/application/frontend/src/lib/ChartMenu/MainChartMenu.svelte +++ b/application/frontend/src/lib/ChartMenu/MainChartMenu.svelte @@ -1,44 +1,68 @@
-

Logs statistic:

-
-
    - {#each headerOptions as option} -
  • { - lastStatisticPeriod.set(option); - }} +
    +

    {chartService}

    +

    + {full.format(total)} log lines in the last {span} +

    +
    + +
    + {#each PERIODS as [value, label]} +
    lastStatisticPeriod.set(value)} > - {option} -
  • {/each} -
+ {label} +
+ {/each} +
- + +
diff --git a/application/frontend/src/lib/ChartMenu/chartData.js b/application/frontend/src/lib/ChartMenu/chartData.js new file mode 100644 index 0000000..e04070b --- /dev/null +++ b/application/frontend/src/lib/ChartMenu/chartData.js @@ -0,0 +1,61 @@ +export const LEVELS = [ + ["error", "Error", "#ff4242"], + ["warn", "Warn", "#ff8a00"], + ["info", "Info", "#87ceeb"], + ["debug", "Debug", "#178f15"], + ["meta", "Meta", "#4e49da"], + ["other", "Other", "#94a3b8"], +]; + +export const PERIODS = [ + ["hour", "Hour"], + ["day", "Day"], + ["month", "Month"], +]; + +// "now" is the unflushed interval, so it is pinned right rather than sorted. +export function orderBuckets(buckets = {}) { + const keys = Object.keys(buckets); + return keys + .filter((b) => b !== "now") + .sort() + .concat(keys.includes("now") ? ["now"] : []); +} + +export function bucketLabel(bucket, unit) { + if (bucket === "now") { + return "now"; + } + const date = new Date(bucket); + if (Number.isNaN(date.getTime())) { + return bucket; + } + if (unit === "hour") { + return date.toLocaleString([], { hour: "2-digit", minute: "2-digit" }); + } + if (unit === "day") { + return date.toLocaleString([], { month: "short", day: "2-digit" }); + } + return date.toLocaleString([], { month: "short", year: "numeric" }); +} + +export function totalLines(buckets = {}) { + return orderBuckets(buckets).reduce( + (sum, b) => sum + LEVELS.reduce((n, [key]) => n + (buckets[b]?.[key] ?? 0), 0), + 0 + ); +} + +export function toChartData(buckets = {}, unit = "hour") { + const ordered = orderBuckets(buckets); + return { + labels: ordered.map((b) => bucketLabel(b, unit)), + datasets: LEVELS.map(([key, name, colour]) => ({ + label: name, + data: ordered.map((b) => buckets[b]?.[key] ?? 0), + stack: "Stack 0", + backgroundColor: colour, + borderWidth: 1, + })), + }; +} diff --git a/application/frontend/src/lib/ChartMenu/chartData.test.mjs b/application/frontend/src/lib/ChartMenu/chartData.test.mjs new file mode 100644 index 0000000..4efb04e --- /dev/null +++ b/application/frontend/src/lib/ChartMenu/chartData.test.mjs @@ -0,0 +1,70 @@ +import assert from "node:assert/strict"; +import { main } from "../../../test/harness.mjs"; +import { orderBuckets, toChartData, totalLines, LEVELS } from "./chartData.js"; + +const RESPONSE = { + "2026-08-08T14:00Z": { debug: 1, error: 2, info: 3, meta: 4, other: 5, warn: 6 }, + "2026-08-08T05:00Z": { debug: 0, error: 0, info: 0, meta: 1, other: 0, warn: 0 }, + now: { debug: 0, error: 7, info: 0, meta: 0, other: 0, warn: 0 }, +}; + +main(async () => { + assert.deepEqual( + orderBuckets(RESPONSE), + ["2026-08-08T05:00Z", "2026-08-08T14:00Z", "now"], + "buckets sort oldest-first with now pinned to the right edge" + ); + + assert.deepEqual(orderBuckets({}), [], "an empty response yields no buckets"); + assert.deepEqual( + orderBuckets({ now: {} }), + ["now"], + "a response holding only the live interval still charts it" + ); + + const data = toChartData(RESPONSE, "hour"); + + assert.equal( + data.datasets.length, + 6, + "every severity gets a series -- meta is the only non-zero level on many containers" + ); + assert.deepEqual( + data.datasets.map((d) => d.label), + ["Error", "Warn", "Info", "Debug", "Meta", "Other"] + ); + + const meta = data.datasets.find((d) => d.label === "Meta"); + assert.deepEqual(meta.data, [1, 4, 0], "series values follow the bucket order"); + + const error = data.datasets.find((d) => d.label === "Error"); + assert.deepEqual(error.data, [0, 2, 7], "the live interval is the last point"); + + assert.equal(data.labels.at(-1), "now", "the live interval is labelled, not timestamped"); + assert.equal(data.labels.length, 3); + assert.ok( + !data.labels.slice(0, -1).includes("1"), + "labels are real timestamps, not the placeholder the emulated data used" + ); + + const sparse = toChartData({ "2026-08-08T14:00Z": { error: 3 } }, "hour"); + for (const series of sparse.datasets) { + assert.ok( + series.data.every((n) => Number.isFinite(n)), + `${series.label} produced a non-numeric point from a sparse bucket` + ); + } + + // 21 in the 14:00 bucket + 1 in the 05:00 bucket + 7 live. + assert.equal(totalLines(RESPONSE), 29, "totals sum every level across every bucket"); + assert.equal(totalLines({}), 0, "an empty response reports nothing to draw"); + assert.equal( + totalLines({ "2026-08-08T14:00Z": { debug: 0, error: 0 } }), + 0, + "all-zero buckets count as nothing to draw, so the empty state shows" + ); + + assert.equal(LEVELS.length, 6); + console.log(` ${data.labels.length} buckets, ${data.datasets.length} series, ${totalLines(RESPONSE)} lines`); + console.log("chart data mapping tests passed"); +}); diff --git a/application/frontend/src/lib/CheckBox/Checkbox.svelte b/application/frontend/src/lib/CheckBox/Checkbox.svelte index 2bb7211..08c91a9 100644 --- a/application/frontend/src/lib/CheckBox/Checkbox.svelte +++ b/application/frontend/src/lib/CheckBox/Checkbox.svelte @@ -1,16 +1,15 @@
@@ -12,7 +10,7 @@ {#each listData as listEl, index}
  • { + onclick={() => { isRowClickable && storeProp?.set && storeProp.set(listEl.name); initialActive = null; listEl.callBack(); @@ -24,13 +22,13 @@

  • - +
    +>
    {/each} diff --git a/application/frontend/src/lib/CommonList/CommonList.test.mjs b/application/frontend/src/lib/CommonList/CommonList.test.mjs new file mode 100644 index 0000000..373fc45 --- /dev/null +++ b/application/frontend/src/lib/CommonList/CommonList.test.mjs @@ -0,0 +1,29 @@ +import assert from "node:assert/strict"; +import { bundleComponent, installDom, importBundle, settle, main } from "../../../test/harness.mjs"; + +main(async () => { + const outfile = await bundleComponent("test/entry.js"); + const { window } = installDom({}); + const bundle = await importBundle(outfile); + const target = window.document.body; + + const empty = bundle.mount(bundle.CommonList, { target, props: { listData: [] } }); + await settle(2); + console.log(` empty list rendered ${target.querySelectorAll("li").length} row(s)`); + assert.equal(target.querySelectorAll("li").length, 0); + bundle.unmount(empty); + + const filled = bundle.mount(bundle.CommonList, { + target, + props: { listData: [{ name: "alpha", ico: "X", callBack: () => {} }] }, + }); + await settle(2); + assert.ok(target.textContent.includes("alpha"), "a populated list should still render"); + assert.ok( + target.querySelector(".highlightedOverlay.active"), + "the first row should start active" + ); + bundle.unmount(filled); + + console.log("CommonList empty-list tests passed"); +}); diff --git a/application/frontend/src/lib/ConfirmationMenu/ConfirmationMenu.scss b/application/frontend/src/lib/ConfirmationMenu/ConfirmationMenu.scss index 84c2858..008e15b 100644 --- a/application/frontend/src/lib/ConfirmationMenu/ConfirmationMenu.scss +++ b/application/frontend/src/lib/ConfirmationMenu/ConfirmationMenu.scss @@ -15,15 +15,6 @@ @include for-mobile { width: 80vw; } - .confirmationName { - margin: 20px 0 20px 0; - } - - .buttonsBox { - display: flex; - justify-content: space-between; - margin-top: 24px; - } .boldText { font-weight: 800; } @@ -60,12 +51,6 @@ margin-top: 24px; } - .confirmationText { - .boldText { - font-weight: 700; - } - } - .log-Tips { line-height: 1; font-size: $main-font-m; diff --git a/application/frontend/src/lib/ConfirmationMenu/ConfirmationMenu.svelte b/application/frontend/src/lib/ConfirmationMenu/ConfirmationMenu.svelte index 57c9aea..2081e9b 100644 --- a/application/frontend/src/lib/ConfirmationMenu/ConfirmationMenu.svelte +++ b/application/frontend/src/lib/ConfirmationMenu/ConfirmationMenu.svelte @@ -1,4 +1,5 @@ @@ -70,13 +86,13 @@
    { + onmouseenter={() => { tipsIsVisible = true; }} - on:mouseleave={() => { + onmouseleave={() => { tipsIsVisible = false; }} - /> +> {#if tipsIsVisible}
    Delete Docker logs - when the option is set to @@ -121,7 +137,7 @@ title={"Delete"} highlighted={true} CB={() => { - deletelogs(); + confirm(); }} />
    -
    +
    { + onkeydown={({ key }) => { key === "Escape" && closeMenu(); }} diff --git a/application/frontend/src/lib/Container/Container.stories.js b/application/frontend/src/lib/Container/Container.stories.js deleted file mode 100644 index 61b8885..0000000 --- a/application/frontend/src/lib/Container/Container.stories.js +++ /dev/null @@ -1,29 +0,0 @@ -// @ts-ignore -import ContainerView from "./ContainerView.svelte"; -import Container from "./Container.svelte"; -import "../../assets/res/onLogsFont.css"; - - - -export default { - component: ContainerView, - title: "Container", - excludeStories: /.*Data$/, - //πŸ‘‡ The argTypes are included so that they are properly displayed in the Actions Panel - argTypes: { - - }, -}; - -const Template = ({ ...args }) => ({ - Component: ContainerView, - props: args, -}); - -export const Default = Template.bind({}); -Default.args = { - - - newHighlighted: false, - -}; diff --git a/application/frontend/src/lib/Container/Container.svelte b/application/frontend/src/lib/Container/Container.svelte index 94cbf8e..d2b26ab 100644 --- a/application/frontend/src/lib/Container/Container.svelte +++ b/application/frontend/src/lib/Container/Container.svelte @@ -1,9 +1,12 @@
    - + {@render children?.()}
    diff --git a/application/frontend/src/lib/Container/ContainerView.svelte b/application/frontend/src/lib/Container/ContainerView.svelte deleted file mode 100644 index d6c9eda..0000000 --- a/application/frontend/src/lib/Container/ContainerView.svelte +++ /dev/null @@ -1,11 +0,0 @@ - - - -

    Slot 1

    -

    Slot 2

    -

    Slot 3

    -
    \ No newline at end of file diff --git a/application/frontend/src/lib/DropDown/DropDown.svelte b/application/frontend/src/lib/DropDown/DropDown.svelte index 4d49950..00f62a1 100644 --- a/application/frontend/src/lib/DropDown/DropDown.svelte +++ b/application/frontend/src/lib/DropDown/DropDown.svelte @@ -4,7 +4,7 @@ diff --git a/application/frontend/src/lib/DropDown/DropDownAddHost.svelte b/application/frontend/src/lib/DropDown/DropDownAddHost.svelte index 3f954f3..4456e1a 100644 --- a/application/frontend/src/lib/DropDown/DropDownAddHost.svelte +++ b/application/frontend/src/lib/DropDown/DropDownAddHost.svelte @@ -3,19 +3,25 @@ import { snipetModalIsVisible, addHostMenuIsVisible, + groupModalIsVisible, + groupBeingEdited, } from "../../Stores/stores.js"; diff --git a/application/frontend/src/lib/DropDown/dropDownRow.svelte b/application/frontend/src/lib/DropDown/dropDownRow.svelte index 94e1e2f..53f6ce3 100644 --- a/application/frontend/src/lib/DropDown/dropDownRow.svelte +++ b/application/frontend/src/lib/DropDown/dropDownRow.svelte @@ -1,23 +1,20 @@ { + onclick={() => { if (titleCallBack) { titleCallBack(); } @@ -30,7 +27,7 @@ style:font-size={`${iconHeight}px`} style:line-height={"100%"} class={rowImage ? `${rowImage}` : ""} - /> +>
    @@ -38,7 +35,7 @@ {#if !disableCheckbox} {:else} -
    +
    {/if} diff --git a/application/frontend/src/lib/GroupModal/GroupModal.scss b/application/frontend/src/lib/GroupModal/GroupModal.scss new file mode 100644 index 0000000..ead3e68 --- /dev/null +++ b/application/frontend/src/lib/GroupModal/GroupModal.scss @@ -0,0 +1,116 @@ +.groupModal { + min-width: 300px; + max-width: 450px; + + @include for-mobile { + min-width: auto; + width: 76vw; + } + + h3 { + margin-bottom: 16px; + // Modal.svelte pins its close button at the top right. + padding-right: 40px; + color: $text-dark-color; + } + + // Matches the Search field, minus its absolutely positioned placeholder, + // which only exists there because an icon is overlaid on that input. + .groupNameInput { + width: 100%; + height: 40px; + box-sizing: border-box; + padding: 0 $normal-padding; + font-family: inherit; + font-size: $main-font-m; + background-color: $inpun-color; + border: 1px solid $text-placeholder-color; + border-radius: $main-border-radius; + color: $text-dark-color; + + &:focus { + outline: none; + border: 2px solid $active-color; + } + } + + .groupModalTree { + max-height: 40vh; + overflow-y: auto; + margin-top: 20px; + + &::-webkit-scrollbar { + width: 10px; + height: 10px; + background-color: rgba(0, 0, 0, 0); + } + + &::-webkit-scrollbar-corner { + display: none; + } + } + + // Echoes .hostHeader / .hostName in the sidebar, which lists the same data. + .groupModalHost { + display: flex; + align-items: center; + justify-content: start; + gap: 12px; + font-weight: bold; + font-size: $main-font-s; + margin-top: $normal-padding; + + &:first-child { + margin-top: 0; + } + + i { + font-size: 16px; + line-height: 1; + } + } + + .groupModalService { + display: flex; + align-items: center; + gap: 12px; + padding: 4px 0; + + &:hover { + opacity: 0.8; + } + + input[type="checkbox"] { + accent-color: $active-color; + width: 16px; + height: 16px; + margin: 0; + flex-shrink: 0; + cursor: pointer; + } + + span { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: $main-font-s; + } + + .disabled { + opacity: 0.2; + } + } + + .groupModalButtons { + display: flex; + justify-content: end; + gap: 8px; + margin-top: 24px; + } + + // Keeps the destructive button away from the one beside it, and collapses to + // nothing when it is not rendered. + #groupModalDelete { + margin-right: auto; + } +} diff --git a/application/frontend/src/lib/GroupModal/GroupModal.svelte b/application/frontend/src/lib/GroupModal/GroupModal.svelte new file mode 100644 index 0000000..44357f9 --- /dev/null +++ b/application/frontend/src/lib/GroupModal/GroupModal.svelte @@ -0,0 +1,187 @@ + + + +
    +

    {editing ? "Edit services group" : "Create services group"}

    + + + +
    + {#each tree as host} +

    + {host.host} +

    + {#each host.services as service} + + {/each} + {/each} +
    + +
    + {#if editing} +
    +
    +
    diff --git a/application/frontend/src/lib/GroupModal/GroupModal.test.mjs b/application/frontend/src/lib/GroupModal/GroupModal.test.mjs new file mode 100644 index 0000000..6c90311 --- /dev/null +++ b/application/frontend/src/lib/GroupModal/GroupModal.test.mjs @@ -0,0 +1,231 @@ +import assert from "node:assert/strict"; +import { + bundleComponent, + installDom, + importBundle, + settle, + jsonResponse, + main, +} from "../../../test/harness.mjs"; + +const HOSTS = [ + { + host: "host1", + services: [ + { serviceName: "api", isDisabled: false, isFavorite: false }, + { serviceName: "web", isDisabled: false, isFavorite: false }, + ], + }, + { + host: "host2", + services: [{ serviceName: "worker", isDisabled: true, isFavorite: false }], + }, +]; + +let calls = []; +let nextResponse = () => jsonResponse({ error: null }); + +async function recordingFetch(url, options = {}) { + calls.push({ + url: String(url), + body: options.body ? JSON.parse(options.body) : null, + }); + return nextResponse(String(url)); +} + +function lastCall(fragment) { + return [...calls].reverse().find((c) => c.url.includes(fragment)); +} + +function setName(window, value) { + const input = window.document.querySelector(".groupNameInput"); + assert.ok(input, "the group name field did not render"); + input.value = value; + input.dispatchEvent(new window.Event("input", { bubbles: true })); +} + +function check(window, host, service) { + const box = window.document.querySelector( + `input[type="checkbox"][data-host="${host}"][data-service="${service}"]` + ); + assert.ok(box, `no checkbox for ${host}/${service}`); + box.click(); + return box; +} + +main(async () => { + const outfile = await bundleComponent("test/entry.js"); + const { window } = installDom({ fetchImpl: recordingFetch }); + const bundle = await importBundle(outfile); + const target = window.document.body; + + const mountModal = async () => { + calls = []; + const app = bundle.mount(bundle.GroupModal, { target, props: { hosts: HOSTS } }); + await settle(); + return app; + }; + + // --- create ------------------------------------------------------------ + bundle.groupBeingEdited.set(null); + bundle.groupModalIsVisible.set(true); + let app = await mountModal(); + + assert.ok(window.document.querySelector(".groupModal"), "the modal did not render"); + const boxes = window.document.querySelectorAll('input[type="checkbox"]'); + console.log(` checkbox tree rendered ${boxes.length} service(s)`); + assert.equal(boxes.length, 3, "every service on every host should be selectable"); + + setName(window, "backend"); + check(window, "host1", "api"); + check(window, "host2", "worker"); + window.document.querySelector("#groupModalSave").click(); + await settle(); + + const created = lastCall("createGroup"); + assert.ok(created, `createGroup was not called: ${calls.map((c) => c.url).join(", ")}`); + assert.deepEqual(created.body, { + name: "backend", + members: [ + { host: "host1", service: "api" }, + { host: "host2", service: "worker" }, + ], + }); + console.log(` create posted ${JSON.stringify(created.body)}`); + assert.ok(lastCall("getGroups"), "the sidebar was not refreshed after a create"); + bundle.unmount(app); + + // --- a group with no members is allowed and renders as an empty folder --- + bundle.groupBeingEdited.set(null); + bundle.groupModalIsVisible.set(true); + app = await mountModal(); + setName(window, "empty folder"); + window.document.querySelector("#groupModalSave").click(); + await settle(); + + const empty = lastCall("createGroup"); + assert.deepEqual( + empty.body, + { name: "empty folder", members: [] }, + "a group with no members should be allowed" + ); + bundle.unmount(app); + + bundle.groups.set([{ name: "empty folder", members: [] }]); + const list = bundle.mount(bundle.ListWithChoise, { target, props: { listData: HOSTS } }); + await settle(); + const section = target.querySelector(".groupSection"); + assert.ok( + section && section.textContent.includes("empty folder"), + "an empty group should still render as a folder" + ); + assert.equal( + section.querySelectorAll(".serviceListItem").length, + 0, + "an empty group should render no rows" + ); + bundle.unmount(list); + bundle.groups.set([]); + + // --- the server is the authority --------------------------------------- + bundle.groupBeingEdited.set(null); + bundle.groupModalIsVisible.set(true); + app = await mountModal(); + nextResponse = (url) => + url.includes("createGroup") + ? jsonResponse({ error: 'Group "taken" already exists' }, 409) + : jsonResponse({ error: null }); + + setName(window, "taken"); + window.document.querySelector("#groupModalSave").click(); + await settle(); + + let toastState = null; + let toastVisible = false; + bundle.toast.subscribe((v) => (toastState = v))(); + bundle.toastIsVisible.subscribe((v) => (toastVisible = v))(); + console.log(` rejected create surfaced: ${toastState.message}`); + assert.ok(toastVisible, "a rejected create should raise a toast"); + assert.equal(toastState.message, 'Group "taken" already exists'); + + let stillOpen = false; + bundle.groupModalIsVisible.subscribe((v) => (stillOpen = v))(); + assert.ok(stillOpen, "a rejected create should leave the modal open"); + nextResponse = () => jsonResponse({ error: null }); + bundle.unmount(app); + + // --- edit -------------------------------------------------------------- + bundle.groupBeingEdited.set({ + name: "backend", + members: [{ host: "host1", service: "api" }], + }); + bundle.groupModalIsVisible.set(true); + app = await mountModal(); + + const nameField = window.document.querySelector(".groupNameInput"); + assert.equal(nameField.value, "backend", "edit mode should pre-fill the name"); + const apiBox = window.document.querySelector( + 'input[type="checkbox"][data-host="host1"][data-service="api"]' + ); + assert.ok(apiBox.checked, "edit mode should pre-check the existing members"); + + setName(window, "backend renamed"); + check(window, "host1", "web"); + check(window, "host1", "api"); + window.document.querySelector("#groupModalSave").click(); + await settle(); + + const updated = lastCall("updateGroup"); + assert.ok(updated, "updateGroup was not called"); + assert.deepEqual(updated.body, { + name: "backend", + newName: "backend renamed", + members: [{ host: "host1", service: "web" }], + }); + console.log(` edit posted ${JSON.stringify(updated.body)}`); + bundle.unmount(app); + + // --- delete ------------------------------------------------------------ + bundle.groupBeingEdited.set({ + name: "backend", + members: [{ host: "host1", service: "api" }], + }); + bundle.groupModalIsVisible.set(true); + app = await mountModal(); + window.document.querySelector("#groupModalDelete").click(); + await settle(); + + const deleted = lastCall("deleteGroup"); + assert.ok(deleted, "deleteGroup was not called"); + assert.deepEqual(deleted.body, { name: "backend" }); + let closed = true; + bundle.groupModalIsVisible.subscribe((v) => (closed = v))(); + assert.equal(closed, false, "a successful delete should close the modal"); + bundle.unmount(app); + + // --- the dropdown row --------------------------------------------------- + bundle.groupModalIsVisible.set(false); + bundle.addHostMenuIsVisible.set(true); + const dropdown = bundle.mount(bundle.DropDownAddHost, { target }); + await settle(); + + const row = [...target.querySelectorAll("tr")].find((tr) => + tr.textContent.includes("Create services group") + ); + assert.ok(row, "the Create services group row is missing"); + assert.ok(row.className.includes("clickable"), "the row should look clickable"); + row.click(); + await settle(); + + let opened = false; + let dropdownOpen = true; + bundle.groupModalIsVisible.subscribe((v) => (opened = v))(); + bundle.addHostMenuIsVisible.subscribe((v) => (dropdownOpen = v))(); + assert.ok(opened, "the row did not open the group modal"); + assert.equal(dropdownOpen, false, "the row did not close the dropdown"); + bundle.unmount(dropdown); + + bundle.groupModalIsVisible.set(false); + bundle.groupBeingEdited.set(null); + console.log("GroupModal tests passed"); +}); diff --git a/application/frontend/src/lib/HostAliasModal/HostAliasModal.scss b/application/frontend/src/lib/HostAliasModal/HostAliasModal.scss new file mode 100644 index 0000000..41fa5dc --- /dev/null +++ b/application/frontend/src/lib/HostAliasModal/HostAliasModal.scss @@ -0,0 +1,63 @@ +.hostAliasModal { + min-width: 320px; + max-width: 420px; + + @include for-mobile { + min-width: auto; + width: 76vw; + } + + h3 { + margin-bottom: 4px; + // Modal.svelte pins its close button at the top right. + padding-right: 40px; + color: $text-dark-color; + } + + .hostAliasReal { + font-family: $mono-font; + font-size: $main-font-s; + color: $text-placeholder-color; + margin-bottom: 16px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .hostAliasInput { + width: 100%; + height: 40px; + box-sizing: border-box; + padding: 0 $normal-padding; + font-family: inherit; + font-size: $main-font-m; + background-color: $inpun-color; + border: 1px solid $text-placeholder-color; + border-radius: $main-border-radius; + color: $text-dark-color; + + &:focus { + outline: none; + border: 2px solid $active-color; + } + } + + .hostAliasHint { + margin-top: 10px; + font-size: $main-font-xs; + line-height: 1.5; + color: $text-placeholder-color; + } + + .hostAliasButtons { + display: flex; + justify-content: end; + margin-top: 24px; + } +} + +.dark-mode .hostAliasModal { + .hostAliasInput:focus { + border-color: $active-color-dark; + } +} diff --git a/application/frontend/src/lib/HostAliasModal/HostAliasModal.svelte b/application/frontend/src/lib/HostAliasModal/HostAliasModal.svelte new file mode 100644 index 0000000..2961ab3 --- /dev/null +++ b/application/frontend/src/lib/HostAliasModal/HostAliasModal.svelte @@ -0,0 +1,75 @@ + + + +
    +

    Rename host

    +

    {$hostBeingRenamed}

    + + +

    + Shown instead of the machine's own hostname. Logs stay stored under + the real name. Leave empty to show the real name again. +

    + +
    +
    +
    +
    diff --git a/application/frontend/src/lib/HostList/HostList.scss b/application/frontend/src/lib/HostList/HostList.scss deleted file mode 100644 index e3130d3..0000000 --- a/application/frontend/src/lib/HostList/HostList.scss +++ /dev/null @@ -1,65 +0,0 @@ -.hostListHeader { - font-size: $main-font-s; - line-height: 1.14; - font-weight: bold; - - ul { - font-weight: 400; - } - .listName { - font-weight: bold; - } - .icon { - display: flex; - align-items: center; - vertical-align: baseline; - position: relative; - margin-bottom: 22px; - } - .log { - margin-bottom: 5px; - margin-right: 10px; - font-size: 16px; - line-height: 0.1; - } -} - -li { - cursor: pointer; - color: white; - padding: 10px 0 10px 0; - margin-bottom: 5px; -} - -.selected { - background-color: rgba(251, 252, 255, 0.1); - padding: 10px 0 10px 15px; - border-left: 5px solid white; - margin: 0 -20px 5px -20px; - - .log.log-Wheel { - padding-right: 20px; - font-size: 20px; - line-height: 1; - float: right; - } -} - -.hosts { - overflow-x: hidden; - overflow-y: scroll; - padding-right: 16px; - height: 36vh; - -} - -.hosts::-webkit-scrollbar { - width: 10px; - height: 10px; - background-color: #00000000; -} - -.hosts::-webkit-scrollbar-thumb { - background-color: #ffffff4a; - border-radius: 10px; -} \ No newline at end of file diff --git a/application/frontend/src/lib/HostList/HostList.svelte b/application/frontend/src/lib/HostList/HostList.svelte deleted file mode 100644 index 774c982..0000000 --- a/application/frontend/src/lib/HostList/HostList.svelte +++ /dev/null @@ -1,40 +0,0 @@ - - -
    -
    -
    - -
    -

    {hostName}

    -
    - -
    -
      - {#if servicesData != null} - {#each servicesData as service} - {#if selectedName.localeCompare(service) == 0} -
    • {service}
    • - - {:else} -
    • { - selectItem(service); - }} - > - {service} -
    • - {/if} - {/each} - {/if} -
    -
    -
    diff --git a/application/frontend/src/lib/Input/Input.svelte b/application/frontend/src/lib/Input/Input.svelte index 12f5989..a00c26e 100644 --- a/application/frontend/src/lib/Input/Input.svelte +++ b/application/frontend/src/lib/Input/Input.svelte @@ -1,10 +1,12 @@
    diff --git a/application/frontend/src/lib/ListWithChoise/ListWithChoise.scss b/application/frontend/src/lib/ListWithChoise/ListWithChoise.scss index 71b9e97..4f10c20 100644 --- a/application/frontend/src/lib/ListWithChoise/ListWithChoise.scss +++ b/application/frontend/src/lib/ListWithChoise/ListWithChoise.scss @@ -92,12 +92,13 @@ } .listElementButton { - .log-Heart { + .log-Heart, + .log-ChartFilled, + .log-WheelFilled { opacity: 1; } - .log-EmptyHeart { - opacity: 0; - } + .log-EmptyHeart, + .log-Chart, .log-Wheel { opacity: 0; } @@ -105,9 +106,8 @@ .serviceListItem:hover { opacity: 0.8; - .log-EmptyHeart { - opacity: 1; - } + .log-EmptyHeart, + .log-Chart, .log-Wheel { opacity: 1; } @@ -139,17 +139,21 @@ .stopedServicesBox { margin-top: 4px; margin-bottom: 4px; + } - .log-Pointer { - font-size: 10px; - cursor: pointer; - padding: 6px; - transform: rotate(0); - &.rotated { - transform: rotate(-90deg); - } + .log-Pointer { + font-size: 10px; + cursor: pointer; + padding: 6px; + transform: rotate(0); + &.rotated { + transform: rotate(-90deg); } } + + .hostToggle { + margin-left: auto; + } .buttonBox { display: flex; gap: 8px; diff --git a/application/frontend/src/lib/ListWithChoise/ListWithChoise.svelte b/application/frontend/src/lib/ListWithChoise/ListWithChoise.svelte index 5ae8482..e746d47 100644 --- a/application/frontend/src/lib/ListWithChoise/ListWithChoise.svelte +++ b/application/frontend/src/lib/ListWithChoise/ListWithChoise.svelte @@ -1,41 +1,65 @@ -
    -
      - {#each sortedData as listEl, index} -
    • -
      { - if (target.id !== headerButton) { - toggleSublistVisible(index); - } - }} - > -
      - +{#snippet serviceRow(host, service, i, idSuffix)} + {@const isCurrent = + `${activeElementName}` === `${host.trim()}-${service.serviceName.trim()}`} +
    • choseService(host, service.serviceName, target)} + > +
      +

      + {service.serviceName} +

      + {#if listElementButton} +
      +
      + openSection( + e, + host, + service.serviceName, + isCurrent && section === "stats" ? "view" : "stats" + )} + > + +
      +
      + openSection( + e, + host, + service.serviceName, + isCurrent && section === "settings" ? "view" : "servicesettings" + )} + > + +
      +
      favoriteToggle(host, service.serviceName)} + > +
      -

      - {listEl.host} -

      - {#if headerButton}
      { - console.log("clicable"); - }} - > - -
      {/if}
      - +
      +
    • +{/snippet} - initialVisitcounter = 1; - } - }} +
      + {#if groupSections.length} +
        + {#each groupSections as group} +
      • +
        toggleGroupVisible(group.name)} + > +
        + +
        +

        + {group.name} +

        +
        { + e.stopPropagation(); + editGroup(group.name); + }} + > + +
        +
        + +
      • + {/each} +
      + {/if} +
        + {#each sortedData as listEl, index} +
      • +
        toggleSublistVisible(index)}> +
        + +
        +

        + {$hostAliases[listEl.host] || listEl.host} +

        +
        { + e.stopPropagation(); + hostBeingRenamed.set(listEl.host); + }} + > + +
        + +
        + +
        { + onclick={() => { toggleArchivedVisible(index); initialVisitcounter = 1; }} > - -

        stoped services

        + +

        stopped services

        +>
          {#each listEl.services as service, i} - {#if service.isDisabled}
        • { - if (!target.id.includes("heart")) { - choseSublistEl(listEl.host, service.serviceName); - lastChosenHost.set(listEl.host); - lastChosenService.set(service.serviceName); - if (!target.className.includes("log")) { - activeMenuOption.set("home"); - } - - initialVisitcounter = 1; - } - }} - > -
          -

          - {service.serviceName} -

          - {#if listElementButton} -
          -
          { - navigate( - `${changeKey}/servicesettings/${listEl.host.trim()}/${service.serviceName.trim()}`, - { replace: true } - ); - - chosenElSettings = `${listEl.host.trim()}-${service.serviceName.trim()}`; - }} - > - -
          -
          { - favoriteToggle(listEl.host, service.serviceName); - }} - > - -
          -
          - {/if} -
          -
          -
        • {/if}{/each} + {#if service.isDisabled}{@render serviceRow(listEl.host, service, i, "Dissabled")}{/if} + {/each}
      • diff --git a/application/frontend/src/lib/ListWithChoise/ListWithChoise.test.mjs b/application/frontend/src/lib/ListWithChoise/ListWithChoise.test.mjs new file mode 100644 index 0000000..2d89b7e --- /dev/null +++ b/application/frontend/src/lib/ListWithChoise/ListWithChoise.test.mjs @@ -0,0 +1,149 @@ +import assert from "node:assert/strict"; +import { + bundleComponent, + installDom, + importBundle, + settle, + jsonResponse, + main, +} from "../../../test/harness.mjs"; + +const HOSTS = [ + { + host: "host1", + services: [ + { serviceName: "api", isDisabled: false, isFavorite: false }, + { serviceName: "web", isDisabled: false, isFavorite: false }, + ], + }, +]; + +const GROUPS = [ + { + name: "backend", + members: [ + { host: "host1", service: "api" }, + { host: "host1", service: "web" }, + { host: "host1", service: "removed" }, + ], + }, +]; + +function textOf(node) { + return node.textContent.replace(/\s+/g, " ").trim(); +} + +main(async () => { + const outfile = await bundleComponent("test/entry.js"); + const { window } = installDom({ fetchImpl: async () => jsonResponse({ error: null }) }); + const bundle = await importBundle(outfile); + const target = window.document.body; + + bundle.groups.set(GROUPS); + bundle.lastChosenHost.set(""); + bundle.lastChosenService.set(""); + + const app = bundle.mount(bundle.ListWithChoise, { + target, + props: { listData: HOSTS }, + }); + await settle(); + + const section = target.querySelector(".groupSection"); + assert.ok(section, "the Groups section did not render"); + assert.ok( + textOf(section).includes("backend"), + `the group heading is missing: ${textOf(section)}` + ); + + const rows = [...section.querySelectorAll(".serviceListItem")]; + const names = rows.map((row) => textOf(row.querySelector("p"))); + console.log(` group rows: ${names.join(", ")}`); + assert.deepEqual( + names, + ["api", "web", "removed"], + "every member should render as a row under the group heading" + ); + + assert.ok( + !rows[0].querySelector("p").className.includes("disabled"), + "a live member should not render disabled" + ); + assert.ok( + rows[2].querySelector("p").className.includes("disabled"), + "a member that no longer exists on any host should render disabled" + ); + + rows[1].querySelector("p").click(); + await settle(); + + let chosenHost = ""; + let chosenService = ""; + bundle.lastChosenHost.subscribe((v) => (chosenHost = v))(); + bundle.lastChosenService.subscribe((v) => (chosenService = v))(); + + console.log(` after clicking "web": ${chosenHost}/${chosenService}`); + assert.equal(chosenHost, "host1", "clicking a group member did not set the host"); + assert.equal(chosenService, "web", "clicking a group member did not set the service"); + assert.ok( + window.location.pathname.endsWith("/view/host1/web"), + `clicking a group member did not navigate: ${window.location.pathname}` + ); + + assert.ok( + textOf(target).includes("host1"), + "the host tree should still render below the groups" + ); + + bundle.unmount(app); + bundle.groups.set([]); + + // The active and stopped service lists render from one shared snippet; their + // rows differ only by an id suffix, so both lists have to be checked. + const MIXED = [ + { + host: "host1", + services: [ + { serviceName: "api", isDisabled: false, isFavorite: true }, + { serviceName: "old", isDisabled: true, isFavorite: false }, + ], + }, + ]; + const tree = bundle.mount(bundle.ListWithChoise, { + target, + props: { listData: MIXED, listElementButton: "true" }, + }); + await settle(); + + const lists = [...target.querySelectorAll("ul.activeServices")]; + assert.equal(lists.length, 2, "expected an active list and a stopped list"); + + const active = [...lists[0].querySelectorAll(".serviceListItem")]; + const stopped = [...lists[1].querySelectorAll(".serviceListItem")]; + console.log( + ` active: ${active.map((r) => textOf(r.querySelector("p")))}, ` + + `stopped: ${stopped.map((r) => textOf(r.querySelector("p")))}` + ); + assert.deepEqual(active.map((r) => textOf(r.querySelector("p"))), ["api"]); + assert.deepEqual(stopped.map((r) => textOf(r.querySelector("p"))), ["old"]); + + assert.ok( + target.querySelector("#heartButton-0"), + "the active row lost its heart button id" + ); + assert.ok( + target.querySelector("#heartButtonDissabled-1"), + "the stopped row lost its suffixed heart button id" + ); + assert.ok( + target.querySelector("#heartButton-0").className.includes("log-Heart"), + "a favourited service should render a filled heart" + ); + assert.ok( + stopped[0].querySelector("p").className.includes("disabled"), + "a stopped service should render disabled" + ); + + bundle.unmount(tree); + console.log("ListWithChoise rendering tests passed"); +}); diff --git a/application/frontend/src/lib/LogsSize/LogsSize.svelte b/application/frontend/src/lib/LogsSize/LogsSize.svelte index dea49cf..814a6fa 100644 --- a/application/frontend/src/lib/LogsSize/LogsSize.svelte +++ b/application/frontend/src/lib/LogsSize/LogsSize.svelte @@ -1,8 +1,7 @@
        - + {#if !isAllLogs}
        +
        {#if !parsedStr}

        {@html messageHtml}

        {:else if $store.transformJson}

        {@html toAnsiHtml(parsedStr.startText)}

        -
        {@html parsedStr.html}
        +
        {JSON.stringify(parsedStr.json, null, 2)}

        {@html toAnsiHtml(parsedStr.endText)}

        {:else}

        {@html messageHtml}

        {/if} - - +
        +
        diff --git a/application/frontend/src/lib/Modal/Modal.svelte b/application/frontend/src/lib/Modal/Modal.svelte index 91d006b..dd3d8cc 100644 --- a/application/frontend/src/lib/Modal/Modal.svelte +++ b/application/frontend/src/lib/Modal/Modal.svelte @@ -1,9 +1,12 @@ - -
        -
        -
        diff --git a/application/frontend/src/lib/SecretModal/DockerComposeSnippet.svelte b/application/frontend/src/lib/SecretModal/DockerComposeSnippet.svelte index 6e08eae..ace3793 100644 --- a/application/frontend/src/lib/SecretModal/DockerComposeSnippet.svelte +++ b/application/frontend/src/lib/SecretModal/DockerComposeSnippet.svelte @@ -1,6 +1,5 @@
        example_onlogs:
        diff --git a/application/frontend/src/lib/SecretModal/DockerSnippet.svelte b/application/frontend/src/lib/SecretModal/DockerSnippet.svelte
        index e315cd8..393cf20 100644
        --- a/application/frontend/src/lib/SecretModal/DockerSnippet.svelte
        +++ b/application/frontend/src/lib/SecretModal/DockerSnippet.svelte
        @@ -1,6 +1,5 @@
         
         
         
        diff --git a/application/frontend/src/lib/SecretModal/SecretModal.svelte b/application/frontend/src/lib/SecretModal/SecretModal.svelte
        index bb84674..15facfe 100644
        --- a/application/frontend/src/lib/SecretModal/SecretModal.svelte
        +++ b/application/frontend/src/lib/SecretModal/SecretModal.svelte
        @@ -15,18 +15,21 @@
           import DockerSnippet from "./DockerSnippet.svelte";
           import DockerComposeSnippet from "./DockerComposeSnippet.svelte";
         
        -  let token = "";
        +  let token = $state("");
           let origin = `${location.origin}${changeKey}`;
           const api = new FetchApi();
        +  let secretError = $state("");
           async function getSecret() {
             try {
               const data = await api.getSecret();
        -      if (data.token) {
        +      if (data?.token) {
                 return data.token;
               }
        -    } catch {
        -      return "2345678901234567";
        +      secretError = data?.error || "Could not obtain a token.";
        +    } catch (e) {
        +      secretError = "Could not obtain a token. Check your connection and try again.";
             }
        +    return "";
           }
         
           function choseSnippetOption(opt = "") {
        @@ -41,7 +44,7 @@
         
        { + onclick_outside={() => { snipetModalIsVisible.set(false); }} > @@ -51,7 +54,7 @@ class={`labelItem clickable ${ $currentSnippedOption === "Docker" ? "active" : "" }`} - on:click={() => { + onclick={() => { choseSnippetOption("Docker"); }} > @@ -61,7 +64,7 @@ class={`labelItem clickable ${ $currentSnippedOption === "DockerCompose" ? "active" : "" }`} - on:click={() => { + onclick={() => { choseSnippetOption("DockerCompose"); }} > @@ -69,6 +72,9 @@
        + {#if secretError} +

        {secretError}

        + {/if} {#if $currentSnippedOption === "Docker"} {/if} @@ -110,9 +116,9 @@ />
      -
      +
      { + onkeydown={(e) => { handleKeydown(e, "Escape", () => { snipetModalIsVisible.set(false); }); diff --git a/application/frontend/src/lib/Stats/Stats.svelte b/application/frontend/src/lib/Stats/Stats.svelte index b577d1e..e4c94b9 100644 --- a/application/frontend/src/lib/Stats/Stats.svelte +++ b/application/frontend/src/lib/Stats/Stats.svelte @@ -8,7 +8,7 @@ } from "../../Stores/stores.js"; import fetchApi from "../../utils/fetch"; - let data = {}; + let data = $state({}); const api = new fetchApi(); let intervalId; @@ -35,24 +35,23 @@ clearInterval(intervalId); }); - $: { - (async () => { - if ($lastChosenHost && $lastChosenService) { - data = await api.getStats({ - period: $lastStatsPeriod, - service: $lastChosenService, - host: $lastChosenHost, - }); - } - })(); - } + $effect(() => { + if ($lastChosenHost && $lastChosenService) { + const period = $lastStatsPeriod; + const service = $lastChosenService; + const host = $lastChosenHost; + api.getStats({ period, service, host }).then((result) => { + data = result; + }); + } + });
      { + onclick={() => { // navigate( // `${changeKey}/stats/${$lastChosenHost}/${$lastChosenService}`, // { @@ -61,11 +60,11 @@ // ); }} title="Counter updates every 1 min since OnLogs started. So, it may cause some asynchrony." - /> +>
      { + onclick={() => { setPeriod(2); }} > @@ -73,7 +72,7 @@
      { + onclick={() => { setPeriod(48); }} > @@ -81,7 +80,7 @@
      { + onclick={() => { setPeriod(336); }} > @@ -89,7 +88,7 @@
      { + onclick={() => { setPeriod(1344); }} > @@ -110,7 +109,7 @@ } }) as [key, name]}
    • { + onclick={async () => { if ($chosenStatus !== key) { chosenStatus.set(key); } else { diff --git a/application/frontend/src/lib/StreamInfo/StreamInfo.svelte b/application/frontend/src/lib/StreamInfo/StreamInfo.svelte index be85a96..f814b7b 100644 --- a/application/frontend/src/lib/StreamInfo/StreamInfo.svelte +++ b/application/frontend/src/lib/StreamInfo/StreamInfo.svelte @@ -4,9 +4,13 @@ import { lastLogTime, WSisMuted, manuallyUnmuted } from "../../Stores/stores"; import { getTimeDifference } from "../../utils/functions"; let lastLogsCheckerInterval = null; - let componentLastLogTime = [] || ""; + let componentLastLogTime = $state([]); - $: componentLastLogTime = getTimeDifference($lastLogTime); + // Not $derived: the interval below also refreshes this so the elapsed time + // keeps counting up while $lastLogTime stays put. + $effect.pre(() => { + componentLastLogTime = getTimeDifference($lastLogTime); + }); let LAST_LOG_INTWRVAL = 5000; function checkLastLogs() { @@ -29,7 +33,7 @@ { + onclick={() => { if ($WSisMuted) { WSisMuted.set(false); manuallyUnmuted.set(true); @@ -38,7 +42,7 @@ manuallyUnmuted.set(false); } }} - /> +>

      Last log line:

      {#if Array.isArray(componentLastLogTime)} @@ -60,6 +64,6 @@ {/if} {/if}
      - +
    • diff --git a/application/frontend/src/lib/Toast/Toast.svelte b/application/frontend/src/lib/Toast/Toast.svelte index f070d80..a376d5d 100644 --- a/application/frontend/src/lib/Toast/Toast.svelte +++ b/application/frontend/src/lib/Toast/Toast.svelte @@ -4,12 +4,13 @@ toast, toastTimeoutId, } from "../../Stores/stores.js"; - import ProgressBar from "../ProgressBar/ProgressBar.svelte"; import Button from "../Button/Button.svelte"; import { handleKeydown } from "../../utils/functions.js"; import { onDestroy, onMount } from "svelte"; import { fly } from "svelte/transition"; - const { tittle, message, status, additionButton } = $toast; + // Reactive: the component is reused across toasts, so a non-reactive + // destructure shows the previous message with the new icon. + let { tittle, message, status, additionButton } = $derived($toast); onDestroy(() => { if ($toastTimeoutId) { @@ -22,11 +23,10 @@ transition:fly={{ y: -200, duration: 200 }} class="toastContainer {status}" > -
      +

      {tittle}

      {message}

      -
      {#if additionButton?.isVisible} @@ -55,7 +55,7 @@
      { + onkeydown={(e) => { handleKeydown(e, "Escape", () => { toastIsVisible.set(false); if (toastTimeoutId) { diff --git a/application/frontend/src/lib/UserMenu/UserManageForm.svelte b/application/frontend/src/lib/UserMenu/UserManageForm.svelte index 80bf475..e7a4504 100644 --- a/application/frontend/src/lib/UserMenu/UserManageForm.svelte +++ b/application/frontend/src/lib/UserMenu/UserManageForm.svelte @@ -1,9 +1,7 @@
      @@ -42,7 +40,7 @@
      diff --git a/application/frontend/src/lib/UserMenu/UserMenu.svelte b/application/frontend/src/lib/UserMenu/UserMenu.svelte index f7e0a92..1ae4a11 100644 --- a/application/frontend/src/lib/UserMenu/UserMenu.svelte +++ b/application/frontend/src/lib/UserMenu/UserMenu.svelte @@ -12,16 +12,15 @@ import Modal from "../Modal/Modal.svelte"; import Input from "../Input/Input.svelte"; - let usersList = []; + let usersList = $state([]); - let chosenUserLogin = ""; - let deleteModalIsOpen = false; - let editModalIsOpen = false; - let userPasswordValue = ""; + let chosenUserLogin = $state(""); + let deleteModalIsOpen = $state(false); + let editModalIsOpen = $state(false); + let userPasswordValue = $state(""); - export let userForAdding = ""; + let { userForAdding = "" } = $props(); - $: userForAdding && addUser(userForAdding); function addUser(u) { if (u) { @@ -133,6 +132,9 @@ onDestroy(() => { delUnsubscribe(), editUnsubscribe(); }); + $effect(() => { + userForAdding && addUser(userForAdding); + });
      @@ -141,33 +143,35 @@ {#if usersList}

      Users:

      -
      - +
      +
      - + + + {#each usersList as user, i}
      UserRoleManage user
      UserRoleManage user
      {user.username} + >{user.username} {#if user.editable} { + onclick={() => { setChosenUserLogin(user.username); showUserEditing(); }}>