diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml
new file mode 100644
index 00000000..2ba9b9c6
--- /dev/null
+++ b/.github/workflows/docs.yaml
@@ -0,0 +1,36 @@
+name: docs
+on:
+ push:
+ branches:
+ - main
+jobs:
+ publish-docs:
+ runs-on: ubuntu-latest
+ steps:
+ -
+ name: Checkout ntfy code
+ uses: actions/checkout@v3
+ -
+ name: Checkout docs pages code
+ uses: actions/checkout@v3
+ with:
+ repository: binwiederhier/ntfy-docs.github.io
+ path: build/ntfy-docs.github.io
+ token: ${{secrets.NTFY_DOCS_PUSH_TOKEN}}
+ # Expires after 1 year, re-generate via
+ # User -> Settings -> Developer options -> Personal Access Tokens -> Fine Grained Token
+ -
+ name: Build docs
+ run: make docs
+ -
+ name: Copy generated docs
+ run: rsync -av --exclude CNAME --delete server/docs/ build/ntfy-docs.github.io/docs/
+ -
+ name: Publish docs
+ run: |
+ cd build/ntfy-docs.github.io
+ git config user.name "GitHub Actions Bot"
+ git config user.email "<>"
+ git add docs/
+ git commit -m "Updated docs"
+ git push origin main
diff --git a/README.md b/README.md
index 7ea7500b..c42f349a 100644
--- a/README.md
+++ b/README.md
@@ -95,6 +95,10 @@ appreciated. A big fat **Thank You** to the folks already sponsoring ntfy:
+
+
+
+
## License
Made with ❤️ by [Philipp C. Heckel](https://heckel.io).
diff --git a/cmd/publish_test.go b/cmd/publish_test.go
index dde279da..f818cdc3 100644
--- a/cmd/publish_test.go
+++ b/cmd/publish_test.go
@@ -17,6 +17,7 @@ func TestCLI_Publish_Subscribe_Poll_Real_Server(t *testing.T) {
app, _, _, _ := newTestApp()
require.Nil(t, app.Run([]string{"ntfy", "publish", "ntfytest", "ntfy unit test " + testMessage}))
+ time.Sleep(3 * time.Second) // Since #502, ntfy.sh writes messages to the cache asynchronously, after a timeout of ~1.5s
app2, _, stdout, _ := newTestApp()
require.Nil(t, app2.Run([]string{"ntfy", "subscribe", "--poll", "ntfytest"}))
diff --git a/cmd/serve.go b/cmd/serve.go
index aff7c7c8..ecc4d4a1 100644
--- a/cmd/serve.go
+++ b/cmd/serve.go
@@ -44,6 +44,8 @@ var flagsServe = append(
altsrc.NewStringFlag(&cli.StringFlag{Name: "firebase-key-file", Aliases: []string{"firebase_key_file", "F"}, EnvVars: []string{"NTFY_FIREBASE_KEY_FILE"}, Usage: "Firebase credentials file; if set additionally publish to FCM topic"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "cache-file", Aliases: []string{"cache_file", "C"}, EnvVars: []string{"NTFY_CACHE_FILE"}, Usage: "cache file used for message caching"}),
altsrc.NewDurationFlag(&cli.DurationFlag{Name: "cache-duration", Aliases: []string{"cache_duration", "b"}, EnvVars: []string{"NTFY_CACHE_DURATION"}, Value: server.DefaultCacheDuration, Usage: "buffer messages for this time to allow `since` requests"}),
+ altsrc.NewIntFlag(&cli.IntFlag{Name: "cache-batch-size", Aliases: []string{"cache_batch_size"}, EnvVars: []string{"NTFY_BATCH_SIZE"}, Usage: "max size of messages to batch together when writing to message cache (if zero, writes are synchronous)"}),
+ altsrc.NewDurationFlag(&cli.DurationFlag{Name: "cache-batch-timeout", Aliases: []string{"cache_batch_timeout"}, EnvVars: []string{"NTFY_CACHE_BATCH_TIMEOUT"}, Usage: "timeout for batched async writes to the message cache (if zero, writes are synchronous)"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "cache-startup-queries", Aliases: []string{"cache_startup_queries"}, EnvVars: []string{"NTFY_CACHE_STARTUP_QUERIES"}, Usage: "queries run when the cache database is initialized"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "auth-file", Aliases: []string{"auth_file", "H"}, EnvVars: []string{"NTFY_AUTH_FILE"}, Usage: "auth database file used for access control"}),
altsrc.NewStringFlag(&cli.StringFlag{Name: "auth-default-access", Aliases: []string{"auth_default_access", "p"}, EnvVars: []string{"NTFY_AUTH_DEFAULT_ACCESS"}, Value: "read-write", Usage: "default permissions if no matching entries in the auth database are found"}),
@@ -110,6 +112,8 @@ func execServe(c *cli.Context) error {
cacheFile := c.String("cache-file")
cacheDuration := c.Duration("cache-duration")
cacheStartupQueries := c.String("cache-startup-queries")
+ cacheBatchSize := c.Int("cache-batch-size")
+ cacheBatchTimeout := c.Duration("cache-batch-timeout")
authFile := c.String("auth-file")
authDefaultAccess := c.String("auth-default-access")
attachmentCacheDir := c.String("attachment-cache-dir")
@@ -233,6 +237,8 @@ func execServe(c *cli.Context) error {
conf.CacheFile = cacheFile
conf.CacheDuration = cacheDuration
conf.CacheStartupQueries = cacheStartupQueries
+ conf.CacheBatchSize = cacheBatchSize
+ conf.CacheBatchTimeout = cacheBatchTimeout
conf.AuthFile = authFile
conf.AuthDefaultRead = authDefaultRead
conf.AuthDefaultWrite = authDefaultWrite
diff --git a/docs/config.md b/docs/config.md
index babb5839..a127a5ac 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -309,6 +309,25 @@ with the given username/password. Be sure to use HTTPS to avoid eavesdropping an
]));
```
+### Example: UnifiedPush
+[UnifiedPush](https://unifiedpush.org) requires that the [application server](https://unifiedpush.org/spec/definitions/#application-server) (e.g. Synapse, Fediverse Server, …)
+has anonymous write access to the [topic](https://unifiedpush.org/spec/definitions/#endpoint) used for push messages.
+The topic names used by UnifiedPush all start with the `up*` prefix. Please refer to the
+**[UnifiedPush documentation](https://unifiedpush.org/users/distributors/ntfy/#limit-access-to-some-users)** for more details.
+
+To enable support for UnifiedPush for private servers (i.e. `auth-default-access: "deny-all"`), you should either
+allow anonymous write access for the entire prefix or explicitly per topic:
+
+=== "Prefix"
+ ```
+ $ ntfy access '*' 'up*' write-only
+ ```
+
+=== "Explicitly"
+ ```
+ $ ntfy access '*' upYzMtZGZiYTY5 write-only
+ ```
+
## E-mail notifications
To allow forwarding messages via e-mail, you can configure an **SMTP server for outgoing messages**. Once configured,
you can set the `X-Email` header to [send messages via e-mail](publish.md#e-mail-notifications) (e.g.
@@ -806,19 +825,27 @@ out [this discussion on Reddit](https://www.reddit.com/r/golang/comments/r9u4ee/
Depending on *how you run it*, here are a few limits that are relevant:
-### WAL for message cache
+### Message cache
By default, the [message cache](#message-cache) (defined by `cache-file`) uses the SQLite default settings, which means it
syncs to disk on every write. For personal servers, this is perfectly adequate. For larger installations, such as ntfy.sh,
the [write-ahead log (WAL)](https://sqlite.org/wal.html) should be enabled, and the sync mode should be adjusted.
See [this article](https://phiresky.github.io/blog/2020/sqlite-performance-tuning/) for details.
+In addition to that, for very high load servers (such as ntfy.sh), it may be beneficial to write messages to the cache
+in batches, and asynchronously. This can be enabled with the `cache-batch-size` and `cache-batch-timeout`. If you start
+seeing `database locked` messages in the logs, you should probably enable that.
+
Here's how ntfy.sh has been tuned in the `server.yml` file:
``` yaml
+cache-batch-size: 25
+cache-batch-timeout: "1s"
cache-startup-queries: |
pragma journal_mode = WAL;
pragma synchronous = normal;
pragma temp_store = memory;
+ pragma busy_timeout = 15000;
+ vacuum;
```
### For systemd services
@@ -971,6 +998,8 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
| `cache-file` | `NTFY_CACHE_FILE` | *filename* | - | If set, messages are cached in a local SQLite database instead of only in-memory. This allows for service restarts without losing messages in support of the since= parameter. See [message cache](#message-cache). |
| `cache-duration` | `NTFY_CACHE_DURATION` | *duration* | 12h | Duration for which messages will be buffered before they are deleted. This is required to support the `since=...` and `poll=1` parameter. Set this to `0` to disable the cache entirely. |
| `cache-startup-queries` | `NTFY_CACHE_STARTUP_QUERIES` | *string (SQL queries)* | - | SQL queries to run during database startup; this is useful for tuning and [enabling WAL mode](#wal-for-message-cache) |
+| `cache-batch-size` | `NTFY_CACHE_BATCH_SIZE` | *int* | 0 | Max size of messages to batch together when writing to message cache (if zero, writes are synchronous) |
+| `cache-batch-timeout` | `NTFY_CACHE_BATCH_TIMEOUT` | *duration* | 0s | Timeout for batched async writes to the message cache (if zero, writes are synchronous) |
| `auth-file` | `NTFY_AUTH_FILE` | *filename* | - | Auth database file used for access control. If set, enables authentication and access control. See [access control](#access-control). |
| `auth-default-access` | `NTFY_AUTH_DEFAULT_ACCESS` | `read-write`, `read-only`, `write-only`, `deny-all` | `read-write` | Default permissions if no matching entries in the auth database are found. Default is `read-write`. |
| `behind-proxy` | `NTFY_BEHIND_PROXY` | *bool* | false | If set, the X-Forwarded-For header is used to determine the visitor IP address instead of the remote address of the connection. |
@@ -1035,6 +1064,8 @@ OPTIONS:
--behind-proxy, --behind_proxy, -P if set, use X-Forwarded-For header to determine visitor IP address (for rate limiting) (default: false) [$NTFY_BEHIND_PROXY]
--cache-duration since, --cache_duration since, -b since buffer messages for this time to allow since requests (default: 12h0m0s) [$NTFY_CACHE_DURATION]
--cache-file value, --cache_file value, -C value cache file used for message caching [$NTFY_CACHE_FILE]
+ --cache-batch-size value, --cache_batch_size value max size of messages to batch together when writing to message cache (if zero, writes are synchronous) (default: 0) [$NTFY_BATCH_SIZE]
+ --cache-batch-timeout value, --cache_batch_timeout value timeout for batched async writes to the message cache (if zero, writes are synchronous) (default: 0s) [$NTFY_CACHE_BATCH_TIMEOUT]
--cache-startup-queries value, --cache_startup_queries value queries run when the cache database is initialized [$NTFY_CACHE_STARTUP_QUERIES]
--cert-file value, --cert_file value, -E value certificate file, if listen-https is set [$NTFY_CERT_FILE]
--config value, -c value config file (default: /etc/ntfy/server.yml) [$NTFY_CONFIG_FILE]
diff --git a/docs/examples.md b/docs/examples.md
index 4ac7a4b2..b9adf443 100644
--- a/docs/examples.md
+++ b/docs/examples.md
@@ -122,6 +122,19 @@ to ntfy at its default URL (`attrs` and other attributes are optional):
priority: 1
```
+## GitHub Actions
+You can send a message during a workflow run with curl. Here is an example sending info about the repo, commit and job status.
+``` yaml
+- name: Actions Ntfy
+ run: |
+ curl \
+ -u ${{ secrets.NTFY_CRED }} \
+ -H "Title: Title here" \
+ -H "Content-Type: text/plain" \
+ -d $'Repo: ${{ github.repository }}\nCommit: ${{ github.sha }}\nRef: ${{ github.ref }}\nStatus: ${{ job.status}}' \
+ ${{ secrets.NTFY_URL }}
+```
+
## Watchtower (shoutrrr)
You can use [shoutrrr](https://github.com/containrrr/shoutrrr) generic webhook support to send
[Watchtower](https://github.com/containrrr/watchtower/) notifications to your ntfy topic.
diff --git a/docs/install.md b/docs/install.md
index 26a63374..34c60fcf 100644
--- a/docs/install.md
+++ b/docs/install.md
@@ -26,37 +26,37 @@ deb/rpm packages.
=== "x86_64/amd64"
```bash
- wget https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_linux_x86_64.tar.gz
- tar zxvf ntfy_1.28.0_linux_x86_64.tar.gz
- sudo cp -a ntfy_1.28.0_linux_x86_64/ntfy /usr/bin/ntfy
- sudo mkdir /etc/ntfy && sudo cp ntfy_1.28.0_linux_x86_64/{client,server}/*.yml /etc/ntfy
+ wget https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_linux_x86_64.tar.gz
+ tar zxvf ntfy_1.29.0_linux_x86_64.tar.gz
+ sudo cp -a ntfy_1.29.0_linux_x86_64/ntfy /usr/bin/ntfy
+ sudo mkdir /etc/ntfy && sudo cp ntfy_1.29.0_linux_x86_64/{client,server}/*.yml /etc/ntfy
sudo ntfy serve
```
=== "armv6"
```bash
- wget https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_linux_armv6.tar.gz
- tar zxvf ntfy_1.28.0_linux_armv6.tar.gz
- sudo cp -a ntfy_1.28.0_linux_armv6/ntfy /usr/bin/ntfy
- sudo mkdir /etc/ntfy && sudo cp ntfy_1.28.0_linux_armv6/{client,server}/*.yml /etc/ntfy
+ wget https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_linux_armv6.tar.gz
+ tar zxvf ntfy_1.29.0_linux_armv6.tar.gz
+ sudo cp -a ntfy_1.29.0_linux_armv6/ntfy /usr/bin/ntfy
+ sudo mkdir /etc/ntfy && sudo cp ntfy_1.29.0_linux_armv6/{client,server}/*.yml /etc/ntfy
sudo ntfy serve
```
=== "armv7/armhf"
```bash
- wget https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_linux_armv7.tar.gz
- tar zxvf ntfy_1.28.0_linux_armv7.tar.gz
- sudo cp -a ntfy_1.28.0_linux_armv7/ntfy /usr/bin/ntfy
- sudo mkdir /etc/ntfy && sudo cp ntfy_1.28.0_linux_armv7/{client,server}/*.yml /etc/ntfy
+ wget https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_linux_armv7.tar.gz
+ tar zxvf ntfy_1.29.0_linux_armv7.tar.gz
+ sudo cp -a ntfy_1.29.0_linux_armv7/ntfy /usr/bin/ntfy
+ sudo mkdir /etc/ntfy && sudo cp ntfy_1.29.0_linux_armv7/{client,server}/*.yml /etc/ntfy
sudo ntfy serve
```
=== "arm64"
```bash
- wget https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_linux_arm64.tar.gz
- tar zxvf ntfy_1.28.0_linux_arm64.tar.gz
- sudo cp -a ntfy_1.28.0_linux_arm64/ntfy /usr/bin/ntfy
- sudo mkdir /etc/ntfy && sudo cp ntfy_1.28.0_linux_arm64/{client,server}/*.yml /etc/ntfy
+ wget https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_linux_arm64.tar.gz
+ tar zxvf ntfy_1.29.0_linux_arm64.tar.gz
+ sudo cp -a ntfy_1.29.0_linux_arm64/ntfy /usr/bin/ntfy
+ sudo mkdir /etc/ntfy && sudo cp ntfy_1.29.0_linux_arm64/{client,server}/*.yml /etc/ntfy
sudo ntfy serve
```
@@ -106,7 +106,7 @@ Manually installing the .deb file:
=== "x86_64/amd64"
```bash
- wget https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_linux_amd64.deb
+ wget https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_linux_amd64.deb
sudo dpkg -i ntfy_*.deb
sudo systemctl enable ntfy
sudo systemctl start ntfy
@@ -114,7 +114,7 @@ Manually installing the .deb file:
=== "armv6"
```bash
- wget https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_linux_armv6.deb
+ wget https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_linux_armv6.deb
sudo dpkg -i ntfy_*.deb
sudo systemctl enable ntfy
sudo systemctl start ntfy
@@ -122,7 +122,7 @@ Manually installing the .deb file:
=== "armv7/armhf"
```bash
- wget https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_linux_armv7.deb
+ wget https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_linux_armv7.deb
sudo dpkg -i ntfy_*.deb
sudo systemctl enable ntfy
sudo systemctl start ntfy
@@ -130,7 +130,7 @@ Manually installing the .deb file:
=== "arm64"
```bash
- wget https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_linux_arm64.deb
+ wget https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_linux_arm64.deb
sudo dpkg -i ntfy_*.deb
sudo systemctl enable ntfy
sudo systemctl start ntfy
@@ -140,28 +140,28 @@ Manually installing the .deb file:
=== "x86_64/amd64"
```bash
- sudo rpm -ivh https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_linux_amd64.rpm
+ sudo rpm -ivh https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_linux_amd64.rpm
sudo systemctl enable ntfy
sudo systemctl start ntfy
```
=== "armv6"
```bash
- sudo rpm -ivh https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_linux_armv6.rpm
+ sudo rpm -ivh https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_linux_armv6.rpm
sudo systemctl enable ntfy
sudo systemctl start ntfy
```
=== "armv7/armhf"
```bash
- sudo rpm -ivh https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_linux_armv7.rpm
+ sudo rpm -ivh https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_linux_armv7.rpm
sudo systemctl enable ntfy
sudo systemctl start ntfy
```
=== "arm64"
```bash
- sudo rpm -ivh https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_linux_arm64.rpm
+ sudo rpm -ivh https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_linux_arm64.rpm
sudo systemctl enable ntfy
sudo systemctl start ntfy
```
@@ -189,18 +189,18 @@ NixOS also supports [declarative setup of the ntfy server](https://search.nixos.
## macOS
The [ntfy CLI](subscribe/cli.md) (`ntfy publish` and `ntfy subscribe` only) is supported on macOS as well.
-To install, please [download the tarball](https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_macOS_all.tar.gz),
+To install, please [download the tarball](https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_macOS_all.tar.gz),
extract it and place it somewhere in your `PATH` (e.g. `/usr/local/bin/ntfy`).
If run as `root`, ntfy will look for its config at `/etc/ntfy/client.yml`. For all other users, it'll look for it at
`~/Library/Application Support/ntfy/client.yml` (sample included in the tarball).
```bash
-curl -L https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_macOS_all.tar.gz > ntfy_1.28.0_macOS_all.tar.gz
-tar zxvf ntfy_1.28.0_macOS_all.tar.gz
-sudo cp -a ntfy_1.28.0_macOS_all/ntfy /usr/local/bin/ntfy
+curl -L https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_macOS_all.tar.gz > ntfy_1.29.0_macOS_all.tar.gz
+tar zxvf ntfy_1.29.0_macOS_all.tar.gz
+sudo cp -a ntfy_1.29.0_macOS_all/ntfy /usr/local/bin/ntfy
mkdir ~/Library/Application\ Support/ntfy
-cp ntfy_1.28.0_macOS_all/client/client.yml ~/Library/Application\ Support/ntfy/client.yml
+cp ntfy_1.29.0_macOS_all/client/client.yml ~/Library/Application\ Support/ntfy/client.yml
ntfy --help
```
@@ -212,7 +212,7 @@ ntfy --help
## Windows
The [ntfy CLI](subscribe/cli.md) (`ntfy publish` and `ntfy subscribe` only) is supported on Windows as well.
-To install, please [download the latest ZIP](https://github.com/binwiederhier/ntfy/releases/download/v1.28.0/ntfy_1.28.0_windows_x86_64.zip),
+To install, please [download the latest ZIP](https://github.com/binwiederhier/ntfy/releases/download/v1.29.0/ntfy_1.29.0_windows_x86_64.zip),
extract it and place the `ntfy.exe` binary somewhere in your `%Path%`.
The default path for the client config file is at `%AppData%\ntfy\client.yml` (not created automatically, sample in the ZIP file).
@@ -431,7 +431,7 @@ Configuration is relatively straightforward. As an example, a minimal configurat
metadata:
name: ntfy
data:
- server.yml: |
+ server.yml: |
# Template: https://github.com/binwiederhier/ntfy/blob/main/server/server.yml
base-url: https://ntfy.sh
```
diff --git a/docs/integrations.md b/docs/integrations.md
index 1ec8372b..d6837a3b 100644
--- a/docs/integrations.md
+++ b/docs/integrations.md
@@ -47,6 +47,7 @@ messages until I finally finish implementing end-to-end encryption.
- [ntfy-middleman](https://github.com/nachotp/ntfy-middleman) - Wraps APIs and send notifications using ntfy.sh on schedule (Python)
- [ntfy-dotnet](https://github.com/nwithan8/ntfy-dotnet) - .NET client library to interact with a ntfy server (C# / .NET)
- [node-ntfy-publish](https://github.com/cityssm/node-ntfy-publish) - A Node package to publish notifications to an ntfy server (Node)
+- [ntfy](https://github.com/jonocarroll/ntfy) - Wraps the ntfy API with pipe-friendly tooling (R)
## CLIs + GUIs
@@ -88,9 +89,16 @@ messages until I finally finish implementing end-to-end encryption.
- [ntfy-to-slack](https://github.com/ozskywalker/ntfy-to-slack) - Tool to subscribe to a ntfy topic and send the messages to a Slack webhook (Go)
- [ansible-ntfy](https://github.com/jpmens/ansible-ntfy) - Ansible action plugin to post JSON messages to ntfy (Python)
- [ntfy-notification-channel](https://github.com/wijourdil/ntfy-notification-channel) - Laravel Notification channel for ntfy (PHP)
+- [ntfy_on_a_chip](https://github.com/gergepalfi/ntfy_on_a_chip) - ESP8266 and ESP32 client code to communicate with ntfy
+- [ntfy-sdk](https://gitlab.com/p2kishimoto/ntfy-sdk) - ntfy client library to send notifications (Rust)
## Blog + forum posts
+- [Tracking layoffs, tech worker demand still high, ntfy, devenv, Markdoc & Mike Bifulco](https://changelog.com/news/tracking-layoffs-tech-worker-demand-still-high-ntfy-devenv-markdoc-mike-bifulco-Y1jW) - 11/2022
+- [Pointer | Issue #367](https://www.pointer.io/archives/a9495a2a6f/) - 11/2022
+- [Envie Push Notifications por POST (de graça e sem cadastro)](https://www.tabnews.com.br/filipedeschamps/envie-push-notifications-por-post-de-graca-e-sem-cadastro) - 11/2022
+- [Push Notifications for KDE](https://volkerkrause.eu/2022/11/12/kde-unifiedpush-push-notifications.html) - 11/2022
+- [TLDR Newsletter Daily Update 2022-11-09](https://tldr.tech/tech/newsletter/2022-11-09) - 11/2022
- [Ntfy.sh – Send push notifications to your phone via PUT/POST](https://news.ycombinator.com/item?id=33517944) ⭐ - 11/2022
- [Ntfy et Jeedom : un plugin](https://lunarok-domotique.com/2022/11/ntfy-et-jeedom/) - 11/2022
- [Crea tu propio servidor de notificaciones con Ntfy](https://blog.parravidales.es/crea-tu-propio-servidor-de-notificaciones-con-ntfy/) - 11/2022
diff --git a/docs/releases.md b/docs/releases.md
index 08e903c0..e662faec 100644
--- a/docs/releases.md
+++ b/docs/releases.md
@@ -4,12 +4,40 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
## ntfy Android app v1.14.0 (UNRELEASED)
+**Bug fixes:**
+
+* Remove timestamp when copying message text ([#471](https://github.com/binwiederhier/ntfy/issues/471), thanks to [@wunter8](https://github.com/wunter8))
+
**Additional translations:**
* Korean (thanks to [@YJSofta0f97461d82447ac](https://hosted.weblate.org/user/YJSofta0f97461d82447ac/))
+## ntfy server v1.30.0 (UNRELREASED)
-## ntfy server v1.29.0 (UNRELEASED)
+**Features:**
+
+* High-load servers: Allow asynchronous batch-writing of messages to cache via `cache-batch-*` options ([#498](https://github.com/binwiederhier/ntfy/issues/498)/[#502](https://github.com/binwiederhier/ntfy/pull/502))
+
+**Documentation:**
+
+* GitHub Actions example ([#492](https://github.com/binwiederhier/ntfy/pull/492), thanks to [@ksurl](https://github.com/ksurl))
+* UnifiedPush ACL clarification ([#497](https://github.com/binwiederhier/ntfy/issues/497), thanks to [@bt90](https://github.com/bt90))
+
+**Other things:**
+
+* Put ntfy.sh docs on GitHub pages to reduce AWS outbound traffic cost ([#491](https://github.com/binwiederhier/ntfy/issues/491))
+* The ntfy.sh server hardware was upgraded to a bigger box. If you'd like to help out carrying the server cost, **[sponsorships and donations](https://github.com/sponsors/binwiederhier)** 💸 would be very much appreciated
+
+## ntfy server v1.29.0
+Released November 12, 2022
+
+This release adds the ability to add rate limit exemptions for IP ranges instead of just specific IP addresses. It also fixes
+a few bugs in the web app and the CLI and adds lots of new examples and install instructions.
+
+Thanks to [some love on HN](https://news.ycombinator.com/item?id=33517944), we got so many new ntfy users trying out ntfy
+and joining the [chat rooms](https://github.com/binwiederhier/ntfy#chat--forum). **Welcome to the ntfy community to all of you!**
+We also got a ton of new **[sponsors and donations](https://github.com/sponsors/binwiederhier)** 💸, which is amazing. I'd like to thank
+all of you for believing in the project, and for helping me pay the server cost. The HN spike increased the AWS cost quite a bit.
**Features:**
diff --git a/go.mod b/go.mod
index c8fb103d..e1f3261d 100644
--- a/go.mod
+++ b/go.mod
@@ -14,8 +14,8 @@ require (
github.com/olebedev/when v0.0.0-20211212231525-59bd4edcf9d6
github.com/stretchr/testify v1.8.1
github.com/urfave/cli/v2 v2.23.5
- golang.org/x/crypto v0.1.0
- golang.org/x/oauth2 v0.1.0 // indirect
+ golang.org/x/crypto v0.3.0
+ golang.org/x/oauth2 v0.2.0 // indirect
golang.org/x/sync v0.1.0
golang.org/x/term v0.2.0
golang.org/x/time v0.2.0
@@ -25,17 +25,19 @@ require (
require github.com/pkg/errors v0.9.1 // indirect
-require firebase.google.com/go/v4 v4.9.0
+require firebase.google.com/go/v4 v4.10.0
require (
- cloud.google.com/go v0.105.0 // indirect
+ cloud.google.com/go v0.107.0 // indirect
cloud.google.com/go/compute v1.12.1 // indirect
cloud.google.com/go/compute/metadata v0.2.1 // indirect
cloud.google.com/go/iam v0.7.0 // indirect
cloud.google.com/go/longrunning v0.3.0 // indirect
github.com/AlekSi/pointer v1.2.0 // indirect
+ github.com/MicahParks/keyfunc v1.5.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead // indirect
+ github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.9 // indirect
@@ -52,7 +54,7 @@ require (
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/appengine/v2 v2.0.2 // indirect
- google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd // indirect
+ google.golang.org/genproto v0.0.0-20221116193143-41c2ba794472 // indirect
google.golang.org/grpc v1.50.1 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/go.sum b/go.sum
index ab3dee01..168bcd42 100644
--- a/go.sum
+++ b/go.sum
@@ -1,32 +1,30 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=
-cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM=
+cloud.google.com/go v0.106.0 h1:AWaMWuZb2oFeiV91OfNHZbmwUhMVuXEaLPm9sqDAOl8=
+cloud.google.com/go v0.106.0/go.mod h1:5NEGxGuIeMQiPaWLwLYZ7kfNWiP6w1+QJK+xqyIT+dw=
+cloud.google.com/go v0.107.0 h1:qkj22L7bgkl6vIeZDlOY2po43Mx/TIa2Wsa7VR+PEww=
+cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I=
cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0=
cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48=
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
cloud.google.com/go/firestore v1.8.0 h1:HokMB9Io0hAyYzlGFeFVMgE3iaPXNvaIsDx5JzblGLI=
cloud.google.com/go/firestore v1.8.0/go.mod h1:r3KB8cAdRIe8znzoPWLw8S6gpDVd9treohhn8b09424=
-cloud.google.com/go/iam v0.6.0 h1:nsqQC88kT5Iwlm4MeNGTpfMWddp6NB/UOLFTH6m1QfQ=
-cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc=
cloud.google.com/go/iam v0.7.0 h1:k4MuwOsS7zGJJ+QfZ5vBK8SgHBAvYN/23BWsiihJ1vs=
cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg=
-cloud.google.com/go/longrunning v0.2.1 h1:x3E/YapFCMe2G1D9qCv9COrBldOwK/n0OC7w9PLzeX0=
-cloud.google.com/go/longrunning v0.2.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE=
cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs=
cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc=
-cloud.google.com/go/storage v1.27.0 h1:YOO045NZI9RKfCj1c5A/ZtuuENUc8OAW+gHdGnDgyMQ=
-cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
cloud.google.com/go/storage v1.28.0 h1:DLrIZ6xkeZX6K70fU/boWx5INJumt6f+nwwWSHXzzGY=
cloud.google.com/go/storage v1.28.0/go.mod h1:qlgZML35PXA3zoEnIkiPLY4/TOkUleufRlu6qmcf7sI=
-firebase.google.com/go/v4 v4.9.0 h1:VCagv+hYOxUGeuyu7J+o2rKJkDp5JQBbA3Bzlof+LMk=
-firebase.google.com/go/v4 v4.9.0/go.mod h1:bHhRkM3VtGJx19rQdW7GDNLdnA8/T6SsnN5nXk/xdw8=
+firebase.google.com/go/v4 v4.10.0 h1:dgK/8uwfJbzc5LZK/GyRRfIkZEDObN9q0kgEXsjlXN4=
+firebase.google.com/go/v4 v4.10.0/go.mod h1:m0gLwPY9fxKggizzglgCNWOGnFnVPifLpqZzo5u3e/A=
github.com/AlekSi/pointer v1.0.0/go.mod h1:1kjywbfcPFCmncIxtk6fIEub6LKrfMz3gc5QKVOSOA8=
github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w=
github.com/AlekSi/pointer v1.2.0/go.mod h1:gZGfd3dpW4vEc/UlyfKKi1roIqcCgwOIvb0tSNSBle0=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/MicahParks/keyfunc v1.5.3 h1:Y+mv+kX3HtL7/dCXXzK4bIDBHg91eunnGGkdndO0RWk=
+github.com/MicahParks/keyfunc v1.5.3/go.mod h1:IdnCilugA0O/99dW+/MkvlyrsX8+L8+x95xuVNtM5jw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
@@ -46,6 +44,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/gabriel-vasile/mimetype v1.4.1 h1:TRWk7se+TOjCYgRth7+1/OYLNiRNIotknkFtf/dnN7Q=
github.com/gabriel-vasile/mimetype v1.4.1/go.mod h1:05Vi0w3Y9c/lNvJOdmIwvrrAhX3rYhfQQCaf9VJcv7M=
+github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
+github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
@@ -79,8 +79,6 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs=
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
-github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU=
-github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ=
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
@@ -101,27 +99,22 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/urfave/cli/v2 v2.23.0 h1:pkly7gKIeYv3olPAeNajNpLjeJrmTPYCoZWaV+2VfvE=
-github.com/urfave/cli/v2 v2.23.0/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI=
github.com/urfave/cli/v2 v2.23.5 h1:xbrU7tAYviSpqeR3X4nEFWUdB/uDZ6DE+HxmRU7Xtyw=
github.com/urfave/cli/v2 v2.23.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
-go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
-go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
-golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
+golang.org/x/crypto v0.2.0 h1:BRXPfhNivWL5Yq0BGQ39a2sW6t44aODpfxkWjYdzewE=
+golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
+golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
+golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -135,13 +128,11 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
-golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.1.0 h1:isLCZuhj4v+tYv7eskaN4v/TM+A1begWWgyVJDdl1+Y=
-golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
+golang.org/x/oauth2 v0.2.0 h1:GtQkldQ9m7yvzCL1V+LrYow3Khe0eJH0w7RbX/VbaIU=
+golang.org/x/oauth2 v0.2.0/go.mod h1:Cwn6afJ8jrQwYMxQDTpISoXmXW9I6qF6vDeuuoX3Ibs=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -153,13 +144,9 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
-golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
-golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -168,8 +155,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
-golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.2.0 h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE=
golang.org/x/time v0.2.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -180,8 +165,6 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
-google.golang.org/api v0.102.0 h1:JxJl2qQ85fRMPNvlZY/enexbxpCjLwGhZUtgfGeQ51I=
-google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo=
google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ=
google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
@@ -193,10 +176,10 @@ google.golang.org/appengine/v2 v2.0.2/go.mod h1:PkgRUWz4o1XOvbqtWTkBtCitEJ5Tp4Ho
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c h1:QgY/XxIAIeccR+Ca/rDdKubLIU9rcJ3xfy1DC/Wd2Oo=
-google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo=
-google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd h1:1eV6KuDTxraYYsYGWksp1thEGP+8dtX/TINL9h+ppiI=
-google.golang.org/genproto v0.0.0-20221107162902-2d387536bcdd/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
+google.golang.org/genproto v0.0.0-20221111202108-142d8a6fa32e h1:azcyH5lGzGy7pkLCbhPe0KkKxsM7c6UA/FZIXImKE7M=
+google.golang.org/genproto v0.0.0-20221111202108-142d8a6fa32e/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
+google.golang.org/genproto v0.0.0-20221116193143-41c2ba794472 h1:kIfItBRE5gkUKpH4H5lNGciZbka1JrmRli3ArqrKFkA=
+google.golang.org/genproto v0.0.0-20221116193143-41c2ba794472/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
diff --git a/server/config.go b/server/config.go
index d8fd429e..1e2b517c 100644
--- a/server/config.go
+++ b/server/config.go
@@ -61,6 +61,8 @@ type Config struct {
CacheFile string
CacheDuration time.Duration
CacheStartupQueries string
+ CacheBatchSize int
+ CacheBatchTimeout time.Duration
AuthFile string
AuthDefaultRead bool
AuthDefaultWrite bool
@@ -114,6 +116,8 @@ func NewConfig() *Config {
FirebaseKeyFile: "",
CacheFile: "",
CacheDuration: DefaultCacheDuration,
+ CacheBatchSize: 0,
+ CacheBatchTimeout: 0,
AuthFile: "",
AuthDefaultRead: true,
AuthDefaultWrite: true,
diff --git a/server/message_cache.go b/server/message_cache.go
index f4433399..bce94220 100644
--- a/server/message_cache.go
+++ b/server/message_cache.go
@@ -44,6 +44,7 @@ const (
published INT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_mid ON messages (mid);
+ CREATE INDEX IF NOT EXISTS idx_time ON messages (time);
CREATE INDEX IF NOT EXISTS idx_topic ON messages (topic);
COMMIT;
`
@@ -92,7 +93,7 @@ const (
// Schema management queries
const (
- currentSchemaVersion = 8
+ currentSchemaVersion = 9
createSchemaVersionTableQuery = `
CREATE TABLE IF NOT EXISTS schemaVersion (
id INT PRIMARY KEY,
@@ -185,15 +186,21 @@ const (
migrate7To8AlterMessagesTableQuery = `
ALTER TABLE messages ADD COLUMN icon TEXT NOT NULL DEFAULT('');
`
+
+ // 8 -> 9
+ migrate8To9AlterMessagesTableQuery = `
+ CREATE INDEX IF NOT EXISTS idx_time ON messages (time);
+ `
)
type messageCache struct {
- db *sql.DB
- nop bool
+ db *sql.DB
+ queue *util.BatchingQueue[*message]
+ nop bool
}
// newSqliteCache creates a SQLite file-backed cache
-func newSqliteCache(filename, startupQueries string, nop bool) (*messageCache, error) {
+func newSqliteCache(filename, startupQueries string, batchSize int, batchTimeout time.Duration, nop bool) (*messageCache, error) {
db, err := sql.Open("sqlite3", filename)
if err != nil {
return nil, err
@@ -201,21 +208,28 @@ func newSqliteCache(filename, startupQueries string, nop bool) (*messageCache, e
if err := setupCacheDB(db, startupQueries); err != nil {
return nil, err
}
- return &messageCache{
- db: db,
- nop: nop,
- }, nil
+ var queue *util.BatchingQueue[*message]
+ if batchSize > 0 || batchTimeout > 0 {
+ queue = util.NewBatchingQueue[*message](batchSize, batchTimeout)
+ }
+ cache := &messageCache{
+ db: db,
+ queue: queue,
+ nop: nop,
+ }
+ go cache.processMessageBatches()
+ return cache, nil
}
// newMemCache creates an in-memory cache
func newMemCache() (*messageCache, error) {
- return newSqliteCache(createMemoryFilename(), "", false)
+ return newSqliteCache(createMemoryFilename(), "", 0, 0, false)
}
// newNopCache creates an in-memory cache that discards all messages;
// it is always empty and can be used if caching is entirely disabled
func newNopCache() (*messageCache, error) {
- return newSqliteCache(createMemoryFilename(), "", true)
+ return newSqliteCache(createMemoryFilename(), "", 0, 0, true)
}
// createMemoryFilename creates a unique memory filename to use for the SQLite backend.
@@ -228,14 +242,23 @@ func createMemoryFilename() string {
return fmt.Sprintf("file:%s?mode=memory&cache=shared", util.RandomString(10))
}
+// AddMessage stores a message to the message cache synchronously, or queues it to be stored at a later date asyncronously.
+// The message is queued only if "batchSize" or "batchTimeout" are passed to the constructor.
func (c *messageCache) AddMessage(m *message) error {
+ if c.queue != nil {
+ c.queue.Enqueue(m)
+ return nil
+ }
return c.addMessages([]*message{m})
}
+// addMessages synchronously stores a match of messages. If the database is locked, the transaction waits until
+// SQLite's busy_timeout is exceeded before erroring out.
func (c *messageCache) addMessages(ms []*message) error {
if c.nop {
return nil
}
+ start := time.Now()
tx, err := c.db.Begin()
if err != nil {
return err
@@ -289,7 +312,12 @@ func (c *messageCache) addMessages(ms []*message) error {
return err
}
}
- return tx.Commit()
+ if err := tx.Commit(); err != nil {
+ log.Error("Cache: Writing %d message(s) failed (took %v)", len(ms), time.Since(start))
+ return err
+ }
+ log.Debug("Cache: Wrote %d message(s) in %v", len(ms), time.Since(start))
+ return nil
}
func (c *messageCache) Messages(topic string, since sinceMarker, scheduled bool) ([]*message, error) {
@@ -395,8 +423,12 @@ func (c *messageCache) Topics() (map[string]*topic, error) {
}
func (c *messageCache) Prune(olderThan time.Time) error {
- _, err := c.db.Exec(pruneMessagesQuery, olderThan.Unix())
- return err
+ start := time.Now()
+ if _, err := c.db.Exec(pruneMessagesQuery, olderThan.Unix()); err != nil {
+ log.Warn("Cache: Pruning failed (after %v): %s", time.Since(start), err.Error())
+ }
+ log.Debug("Cache: Pruning successful (took %v)", time.Since(start))
+ return nil
}
func (c *messageCache) AttachmentBytesUsed(sender string) (int64, error) {
@@ -417,6 +449,17 @@ func (c *messageCache) AttachmentBytesUsed(sender string) (int64, error) {
return size, nil
}
+func (c *messageCache) processMessageBatches() {
+ if c.queue == nil {
+ return
+ }
+ for messages := range c.queue.Dequeue() {
+ if err := c.addMessages(messages); err != nil {
+ log.Error("Cache: %s", err.Error())
+ }
+ }
+}
+
func readMessages(rows *sql.Rows) ([]*message, error) {
defer rows.Close()
messages := make([]*message, 0)
@@ -542,6 +585,8 @@ func setupCacheDB(db *sql.DB, startupQueries string) error {
return migrateFrom6(db)
} else if schemaVersion == 7 {
return migrateFrom7(db)
+ } else if schemaVersion == 8 {
+ return migrateFrom8(db)
}
return fmt.Errorf("unexpected schema version found: %d", schemaVersion)
}
@@ -647,5 +692,16 @@ func migrateFrom7(db *sql.DB) error {
if _, err := db.Exec(updateSchemaVersion, 8); err != nil {
return err
}
+ return migrateFrom8(db)
+}
+
+func migrateFrom8(db *sql.DB) error {
+ log.Info("Migrating cache database schema: from 8 to 9")
+ if _, err := db.Exec(migrate8To9AlterMessagesTableQuery); err != nil {
+ return err
+ }
+ if _, err := db.Exec(updateSchemaVersion, 9); err != nil {
+ return err
+ }
return nil // Update this when a new version is added
}
diff --git a/server/message_cache_test.go b/server/message_cache_test.go
index c72debca..c3b7305e 100644
--- a/server/message_cache_test.go
+++ b/server/message_cache_test.go
@@ -450,7 +450,7 @@ func TestSqliteCache_StartupQueries_WAL(t *testing.T) {
startupQueries := `pragma journal_mode = WAL;
pragma synchronous = normal;
pragma temp_store = memory;`
- db, err := newSqliteCache(filename, startupQueries, false)
+ db, err := newSqliteCache(filename, startupQueries, 0, 0, false)
require.Nil(t, err)
require.Nil(t, db.AddMessage(newDefaultMessage("mytopic", "some message")))
require.FileExists(t, filename)
@@ -461,7 +461,7 @@ pragma temp_store = memory;`
func TestSqliteCache_StartupQueries_None(t *testing.T) {
filename := newSqliteTestCacheFile(t)
startupQueries := ""
- db, err := newSqliteCache(filename, startupQueries, false)
+ db, err := newSqliteCache(filename, startupQueries, 0, 0, false)
require.Nil(t, err)
require.Nil(t, db.AddMessage(newDefaultMessage("mytopic", "some message")))
require.FileExists(t, filename)
@@ -472,7 +472,7 @@ func TestSqliteCache_StartupQueries_None(t *testing.T) {
func TestSqliteCache_StartupQueries_Fail(t *testing.T) {
filename := newSqliteTestCacheFile(t)
startupQueries := `xx error`
- _, err := newSqliteCache(filename, startupQueries, false)
+ _, err := newSqliteCache(filename, startupQueries, 0, 0, false)
require.Error(t, err)
}
@@ -501,7 +501,7 @@ func TestMemCache_NopCache(t *testing.T) {
}
func newSqliteTestCache(t *testing.T) *messageCache {
- c, err := newSqliteCache(newSqliteTestCacheFile(t), "", false)
+ c, err := newSqliteCache(newSqliteTestCacheFile(t), "", 0, 0, false)
if err != nil {
t.Fatal(err)
}
@@ -513,7 +513,7 @@ func newSqliteTestCacheFile(t *testing.T) string {
}
func newSqliteTestCacheFromFile(t *testing.T, filename, startupQueries string) *messageCache {
- c, err := newSqliteCache(filename, startupQueries, false)
+ c, err := newSqliteCache(filename, startupQueries, 0, 0, false)
if err != nil {
t.Fatal(err)
}
diff --git a/server/server.go b/server/server.go
index ef09100d..fe729b1b 100644
--- a/server/server.go
+++ b/server/server.go
@@ -159,7 +159,7 @@ func createMessageCache(conf *Config) (*messageCache, error) {
if conf.CacheDuration == 0 {
return newNopCache()
} else if conf.CacheFile != "" {
- return newSqliteCache(conf.CacheFile, conf.CacheStartupQueries, false)
+ return newSqliteCache(conf.CacheFile, conf.CacheStartupQueries, conf.CacheBatchSize, conf.CacheBatchTimeout, false)
}
return newMemCache()
}
@@ -491,6 +491,7 @@ func (s *Server) handlePublishWithoutResponse(r *http.Request, v *visitor) (*mes
log.Debug("%s Message delayed, will process later", logMessagePrefix(v, m))
}
if cache {
+ log.Debug("%s Adding message to cache", logMessagePrefix(v, m))
if err := s.messageCache.AddMessage(m); err != nil {
return nil, err
}
diff --git a/server/server.yml b/server/server.yml
index 245bc4da..1b268995 100644
--- a/server/server.yml
+++ b/server/server.yml
@@ -53,6 +53,12 @@
# pragma journal_mode = WAL;
# pragma synchronous = normal;
# pragma temp_store = memory;
+# pragma busy_timeout = 15000;
+# vacuum;
+#
+# The "cache-batch-size" and "cache-batch-timeout" parameter allow enabling async batch writing
+# of messages. If set, messages will be queued and written to the database in batches of the given
+# size, or after the given timeout. This is only required for high volume servers.
#
# Debian/RPM package users:
# Use /var/cache/ntfy/cache.db as cache file to avoid permission issues. The package
@@ -65,6 +71,8 @@
# cache-file:
# cache-duration: "12h"
# cache-startup-queries:
+# cache-batch-size: 0
+# cache-batch-timeout: "0ms"
# If set, access to the ntfy server and API can be controlled on a granular level using
# the 'ntfy user' and 'ntfy access' commands. See the --help pages for details, or check the docs.
@@ -173,8 +181,9 @@
# Rate limiting: Allowed GET/PUT/POST requests per second, per visitor:
# - visitor-request-limit-burst is the initial bucket of requests each visitor has
# - visitor-request-limit-replenish is the rate at which the bucket is refilled
-# - visitor-request-limit-exempt-hosts is a comma-separated list of hostnames and IPs to be
-# exempt from request rate limiting; hostnames are resolved at the time the server is started
+# - visitor-request-limit-exempt-hosts is a comma-separated list of hostnames, IPs or CIDRs to be
+# exempt from request rate limiting. Hostnames are resolved at the time the server is started.
+# Example: "1.2.3.4,ntfy.example.com,8.7.6.0/24"
#
# visitor-request-limit-burst: 60
# visitor-request-limit-replenish: "5s"
diff --git a/util/batching_queue.go b/util/batching_queue.go
new file mode 100644
index 00000000..85ba9be9
--- /dev/null
+++ b/util/batching_queue.go
@@ -0,0 +1,86 @@
+package util
+
+import (
+ "sync"
+ "time"
+)
+
+// BatchingQueue is a queue that creates batches of the enqueued elements based on a
+// max batch size and a batch timeout.
+//
+// Example:
+//
+// q := NewBatchingQueue[int](2, 500 * time.Millisecond)
+// go func() {
+// for batch := range q.Dequeue() {
+// fmt.Println(batch)
+// }
+// }()
+// q.Enqueue(1)
+// q.Enqueue(2)
+// q.Enqueue(3)
+// time.Sleep(time.Second)
+//
+// This example will emit batch [1, 2] immediately (because the batch size is 2), and
+// a batch [3] after 500ms.
+type BatchingQueue[T any] struct {
+ batchSize int
+ timeout time.Duration
+ in []T
+ out chan []T
+ mu sync.Mutex
+}
+
+// NewBatchingQueue creates a new BatchingQueue
+func NewBatchingQueue[T any](batchSize int, timeout time.Duration) *BatchingQueue[T] {
+ q := &BatchingQueue[T]{
+ batchSize: batchSize,
+ timeout: timeout,
+ in: make([]T, 0),
+ out: make(chan []T),
+ }
+ go q.timeoutTicker()
+ return q
+}
+
+// Enqueue enqueues an element to the queue. If the configured batch size is reached,
+// the batch will be emitted immediately.
+func (q *BatchingQueue[T]) Enqueue(element T) {
+ q.mu.Lock()
+ q.in = append(q.in, element)
+ var elements []T
+ if len(q.in) == q.batchSize {
+ elements = q.dequeueAll()
+ }
+ q.mu.Unlock()
+ if len(elements) > 0 {
+ q.out <- elements
+ }
+}
+
+// Dequeue returns a channel emitting batches of elements
+func (q *BatchingQueue[T]) Dequeue() <-chan []T {
+ return q.out
+}
+
+func (q *BatchingQueue[T]) dequeueAll() []T {
+ elements := make([]T, len(q.in))
+ copy(elements, q.in)
+ q.in = q.in[:0]
+ return elements
+}
+
+func (q *BatchingQueue[T]) timeoutTicker() {
+ if q.timeout == 0 {
+ return
+ }
+ ticker := time.NewTicker(q.timeout)
+ for range ticker.C {
+ q.mu.Lock()
+ elements := q.dequeueAll()
+ q.mu.Unlock()
+ if len(elements) > 0 {
+ q.out <- elements
+ }
+ }
+}
diff --git a/util/batching_queue_test.go b/util/batching_queue_test.go
new file mode 100644
index 00000000..b3c41a4c
--- /dev/null
+++ b/util/batching_queue_test.go
@@ -0,0 +1,58 @@
+package util_test
+
+import (
+ "github.com/stretchr/testify/require"
+ "heckel.io/ntfy/util"
+ "math/rand"
+ "sync"
+ "testing"
+ "time"
+)
+
+func TestBatchingQueue_InfTimeout(t *testing.T) {
+ q := util.NewBatchingQueue[int](25, 1*time.Hour)
+ batches, total := make([][]int, 0), 0
+ var mu sync.Mutex
+ go func() {
+ for batch := range q.Dequeue() {
+ mu.Lock()
+ batches = append(batches, batch)
+ total += len(batch)
+ mu.Unlock()
+ }
+ }()
+ for i := 0; i < 101; i++ {
+ go q.Enqueue(i)
+ }
+ time.Sleep(time.Second)
+ mu.Lock()
+ require.Equal(t, 100, total) // One is missing, stuck in the last batch!
+ require.Equal(t, 4, len(batches))
+ mu.Unlock()
+}
+
+func TestBatchingQueue_WithTimeout(t *testing.T) {
+ q := util.NewBatchingQueue[int](25, 100*time.Millisecond)
+ batches, total := make([][]int, 0), 0
+ var mu sync.Mutex
+ go func() {
+ for batch := range q.Dequeue() {
+ mu.Lock()
+ batches = append(batches, batch)
+ total += len(batch)
+ mu.Unlock()
+ }
+ }()
+ for i := 0; i < 101; i++ {
+ go func(i int) {
+ time.Sleep(time.Duration(rand.Intn(700)) * time.Millisecond)
+ q.Enqueue(i)
+ }(i)
+ }
+ time.Sleep(time.Second)
+ mu.Lock()
+ require.Equal(t, 101, total)
+ require.True(t, len(batches) > 4) // 101/25
+ require.True(t, len(batches) < 21)
+ mu.Unlock()
+}
diff --git a/web/package-lock.json b/web/package-lock.json
index d4338d92..da6edf3d 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -3069,14 +3069,14 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A=="
},
"node_modules/@mui/base": {
- "version": "5.0.0-alpha.105",
- "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.105.tgz",
- "integrity": "sha512-4IPBcJQIgVVXQvN6DQMoCHed52GBtwSqYs0jD0dDcMR3o76AodQtpEeWFz3p7mJoc6f/IHBl9U6jEfL1r/kM4g==",
+ "version": "5.0.0-alpha.106",
+ "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.106.tgz",
+ "integrity": "sha512-xJQQtwPCPwr6hGWTBdvDwHYwExn3Bw7nPQkN8Fuz8kHpZqoMVWQvvaFS557AIkkI2AFLV3DxVIMjbCvrIntBWg==",
"dependencies": {
- "@babel/runtime": "^7.19.0",
+ "@babel/runtime": "^7.20.1",
"@emotion/is-prop-valid": "^1.2.0",
- "@mui/types": "^7.2.0",
- "@mui/utils": "^5.10.9",
+ "@mui/types": "^7.2.1",
+ "@mui/utils": "^5.10.14",
"@popperjs/core": "^2.11.6",
"clsx": "^1.2.1",
"prop-types": "^15.8.1",
@@ -3101,20 +3101,20 @@
}
},
"node_modules/@mui/core-downloads-tracker": {
- "version": "5.10.13",
- "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.13.tgz",
- "integrity": "sha512-zWkWPV/SaNdsIdxAWiuVGZ+Ue3BkfSIlU/BFIrJmuUcwiIa7gQsbI/DOpj1KzLvqZhdEe2wC1aG4nCHfzgc1Hg==",
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.14.tgz",
+ "integrity": "sha512-qLgIJNOR9Dre8JiZ/neVzOf4jf88J6YtOkQqugtMrleLjbfRVUSS4LWl9CSOjNq76quYdmYWnSDgfQqOooT2cQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui"
}
},
"node_modules/@mui/icons-material": {
- "version": "5.10.9",
- "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.10.9.tgz",
- "integrity": "sha512-sqClXdEM39WKQJOQ0ZCPTptaZgqwibhj2EFV9N0v7BU1PO8y4OcX/a2wIQHn4fNuDjIZktJIBrmU23h7aqlGgg==",
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.10.14.tgz",
+ "integrity": "sha512-qtH60slQa+7MZRn6kyui8rKuoGDglPqaHX+pzBKNvd8JCOlrnfY5DmGGDdToTXyXl8xJ8nhANZbrbpg7UVKq/Q==",
"dependencies": {
- "@babel/runtime": "^7.19.0"
+ "@babel/runtime": "^7.20.1"
},
"engines": {
"node": ">=12.0.0"
@@ -3135,16 +3135,16 @@
}
},
"node_modules/@mui/material": {
- "version": "5.10.13",
- "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.10.13.tgz",
- "integrity": "sha512-TkkT1rNc0/hhL4/+zv4gYcA6egNWBH/1Tz+azoTnQIUdZ32fgwFI2pFX2KVJNTt30xnLznxDWtTv7ilmJQ52xw==",
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.10.14.tgz",
+ "integrity": "sha512-HWzKVAykePMx54WtxVwZyL1W4k3xlHYIqwMw0CaXAvgB3UE9yjABZuuGr8vG5Z6CSNWamzd+s1x8u7pQPFl9og==",
"dependencies": {
- "@babel/runtime": "^7.19.0",
- "@mui/base": "5.0.0-alpha.105",
- "@mui/core-downloads-tracker": "^5.10.13",
- "@mui/system": "^5.10.13",
- "@mui/types": "^7.2.0",
- "@mui/utils": "^5.10.9",
+ "@babel/runtime": "^7.20.1",
+ "@mui/base": "5.0.0-alpha.106",
+ "@mui/core-downloads-tracker": "^5.10.14",
+ "@mui/system": "^5.10.14",
+ "@mui/types": "^7.2.1",
+ "@mui/utils": "^5.10.14",
"@types/react-transition-group": "^4.4.5",
"clsx": "^1.2.1",
"csstype": "^3.1.1",
@@ -3179,12 +3179,12 @@
}
},
"node_modules/@mui/private-theming": {
- "version": "5.10.9",
- "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.10.9.tgz",
- "integrity": "sha512-BN7/CnsVPVyBaQpDTij4uV2xGYHHHhOgpdxeYLlIu+TqnsVM7wUeF+37kXvHovxM6xmL5qoaVUD98gDC0IZnHg==",
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.10.14.tgz",
+ "integrity": "sha512-3aIBe8WK65CwAPDY8nB11hYnzE1CZMymi76UnaFrA/DdGDwl5Y8F6uB+StKrkVmsqF1po7Mp2odqVkHj320gXw==",
"dependencies": {
- "@babel/runtime": "^7.19.0",
- "@mui/utils": "^5.10.9",
+ "@babel/runtime": "^7.20.1",
+ "@mui/utils": "^5.10.14",
"prop-types": "^15.8.1"
},
"engines": {
@@ -3205,12 +3205,12 @@
}
},
"node_modules/@mui/styled-engine": {
- "version": "5.10.8",
- "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.10.8.tgz",
- "integrity": "sha512-w+y8WI18EJV6zM/q41ug19cE70JTeO6sWFsQ7tgePQFpy6ToCVPh0YLrtqxUZXSoMStW5FMw0t9fHTFAqPbngw==",
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.10.14.tgz",
+ "integrity": "sha512-bgKdM57ExogWpIfhL/ngSlzF4FhbH00vYF+Y5VALTob4uslFqje0xzoWmbfcCn4cZt2NXxZJIwhsq4vzo5itlw==",
"dependencies": {
- "@babel/runtime": "^7.19.0",
- "@emotion/cache": "^11.10.3",
+ "@babel/runtime": "^7.20.1",
+ "@emotion/cache": "^11.10.5",
"csstype": "^3.1.1",
"prop-types": "^15.8.1"
},
@@ -3236,15 +3236,15 @@
}
},
"node_modules/@mui/system": {
- "version": "5.10.13",
- "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.10.13.tgz",
- "integrity": "sha512-Xzx26Asu5fVlm0ucm+gnJmeX4Y1isrpVDvqxX4yJaOT7Fzmd8Lfq9ih3QMfZajns5LMtUiOuCQlVFRtUG5IY7A==",
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.10.14.tgz",
+ "integrity": "sha512-2de7XCjRb1j8Od0Stmo0LwFMLpOMNT4wzfINuExXI1TVSuyxXIXUxiC5FEgJW3GMvf/a7SUR8VOiMoKlKWzukw==",
"dependencies": {
- "@babel/runtime": "^7.19.0",
- "@mui/private-theming": "^5.10.9",
- "@mui/styled-engine": "^5.10.8",
- "@mui/types": "^7.2.0",
- "@mui/utils": "^5.10.9",
+ "@babel/runtime": "^7.20.1",
+ "@mui/private-theming": "^5.10.14",
+ "@mui/styled-engine": "^5.10.14",
+ "@mui/types": "^7.2.1",
+ "@mui/utils": "^5.10.14",
"clsx": "^1.2.1",
"csstype": "^3.1.1",
"prop-types": "^15.8.1"
@@ -3275,9 +3275,9 @@
}
},
"node_modules/@mui/types": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.0.tgz",
- "integrity": "sha512-lGXtFKe5lp3UxTBGqKI1l7G8sE2xBik8qCfrLHD5olwP/YU0/ReWoWT7Lp1//ri32dK39oPMrJN8TgbkCSbsNA==",
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.1.tgz",
+ "integrity": "sha512-c5mSM7ivD8EsqK6HUi9hQPr5V7TJ/IRThUQ9nWNYPdhCGriTSQV4vL6DflT99LkM+wLiIS1rVjphpEWxERep7A==",
"peerDependencies": {
"@types/react": "*"
},
@@ -3288,11 +3288,11 @@
}
},
"node_modules/@mui/utils": {
- "version": "5.10.9",
- "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.10.9.tgz",
- "integrity": "sha512-2tdHWrq3+WCy+G6TIIaFx3cg7PorXZ71P375ExuX61od1NOAJP1mK90VxQ8N4aqnj2vmO3AQDkV4oV2Ktvt4bA==",
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.10.14.tgz",
+ "integrity": "sha512-12p59+wDZpA++XVJmKwqsZmrA1nmUQ5d0a1yQWtcDjxNyER1EDzozYN/db+FY2i5ceQh2TynPTEwGms2mXDwFg==",
"dependencies": {
- "@babel/runtime": "^7.19.0",
+ "@babel/runtime": "^7.20.1",
"@types/prop-types": "^15.7.5",
"@types/react-is": "^16.7.1 || ^17.0.0",
"prop-types": "^15.8.1",
@@ -3370,9 +3370,9 @@
}
},
"node_modules/@pmmmwh/react-refresh-webpack-plugin": {
- "version": "0.5.8",
- "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.8.tgz",
- "integrity": "sha512-wxXRwf+IQ6zvHSJZ+5T2RQNEsq+kx4jKRXfFvdt3nBIUzJUAvXEFsUeoaohDe/Kr84MTjGwcuIUPNcstNJORsA==",
+ "version": "0.5.9",
+ "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.9.tgz",
+ "integrity": "sha512-7QV4cqUwhkDIHpMAZ9mestSJ2DMIotVTbOUwbiudhjCRTAWWKIaBecELiEM2LT3AHFeOAaHIcFu4dbXjX+9GBA==",
"dependencies": {
"ansi-html-community": "^0.0.8",
"common-path-prefix": "^3.0.0",
@@ -3380,7 +3380,7 @@
"error-stack-parser": "^2.0.6",
"find-up": "^5.0.0",
"html-entities": "^2.1.0",
- "loader-utils": "^2.0.0",
+ "loader-utils": "^2.0.3",
"schema-utils": "^3.0.0",
"source-map": "^0.7.3"
},
@@ -4090,13 +4090,13 @@
"integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA=="
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.1.tgz",
- "integrity": "sha512-LyR6x784JCiJ1j6sH5Y0K6cdExqCCm8DJUTcwG5ThNXJj/G8o5E56u5EdG4SLy+bZAwZBswC+GYn3eGdttBVCg==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.43.0.tgz",
+ "integrity": "sha512-wNPzG+eDR6+hhW4yobEmpR36jrqqQv1vxBq5LJO3fBAktjkvekfr4BRl+3Fn1CM/A+s8/EiGUbOMDoYqWdbtXA==",
"dependencies": {
- "@typescript-eslint/scope-manager": "5.42.1",
- "@typescript-eslint/type-utils": "5.42.1",
- "@typescript-eslint/utils": "5.42.1",
+ "@typescript-eslint/scope-manager": "5.43.0",
+ "@typescript-eslint/type-utils": "5.43.0",
+ "@typescript-eslint/utils": "5.43.0",
"debug": "^4.3.4",
"ignore": "^5.2.0",
"natural-compare-lite": "^1.4.0",
@@ -4136,11 +4136,11 @@
}
},
"node_modules/@typescript-eslint/experimental-utils": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.42.1.tgz",
- "integrity": "sha512-qona75z2MLpeZADEuCet5Pwvh1g/0cWScEEDy43chuUPc4klgDiwz5hLFk5dHcjFEETSYQHRPYiiHKW24EMPjw==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.43.0.tgz",
+ "integrity": "sha512-WkT637CumTJbm/hRbFfnHBMgfUYTKr08LitVsD7gQId7bi6rnkx3pu3jac67lmp5ObW4MpJ9SNFZAIOUB/Qbsw==",
"dependencies": {
- "@typescript-eslint/utils": "5.42.1"
+ "@typescript-eslint/utils": "5.43.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -4154,13 +4154,13 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.1.tgz",
- "integrity": "sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.43.0.tgz",
+ "integrity": "sha512-2iHUK2Lh7PwNUlhFxxLI2haSDNyXvebBO9izhjhMoDC+S3XI9qt2DGFUsiJ89m2k7gGYch2aEpYqV5F/+nwZug==",
"dependencies": {
- "@typescript-eslint/scope-manager": "5.42.1",
- "@typescript-eslint/types": "5.42.1",
- "@typescript-eslint/typescript-estree": "5.42.1",
+ "@typescript-eslint/scope-manager": "5.43.0",
+ "@typescript-eslint/types": "5.43.0",
+ "@typescript-eslint/typescript-estree": "5.43.0",
"debug": "^4.3.4"
},
"engines": {
@@ -4180,12 +4180,12 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.1.tgz",
- "integrity": "sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.43.0.tgz",
+ "integrity": "sha512-XNWnGaqAtTJsUiZaoiGIrdJYHsUOd3BZ3Qj5zKp9w6km6HsrjPk/TGZv0qMTWyWj0+1QOqpHQ2gZOLXaGA9Ekw==",
"dependencies": {
- "@typescript-eslint/types": "5.42.1",
- "@typescript-eslint/visitor-keys": "5.42.1"
+ "@typescript-eslint/types": "5.43.0",
+ "@typescript-eslint/visitor-keys": "5.43.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -4196,12 +4196,12 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.42.1.tgz",
- "integrity": "sha512-WWiMChneex5w4xPIX56SSnQQo0tEOy5ZV2dqmj8Z371LJ0E+aymWD25JQ/l4FOuuX+Q49A7pzh/CGIQflxMVXg==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.43.0.tgz",
+ "integrity": "sha512-K21f+KY2/VvYggLf5Pk4tgBOPs2otTaIHy2zjclo7UZGLyFH86VfUOm5iq+OtDtxq/Zwu2I3ujDBykVW4Xtmtg==",
"dependencies": {
- "@typescript-eslint/typescript-estree": "5.42.1",
- "@typescript-eslint/utils": "5.42.1",
+ "@typescript-eslint/typescript-estree": "5.43.0",
+ "@typescript-eslint/utils": "5.43.0",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
},
@@ -4222,9 +4222,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.1.tgz",
- "integrity": "sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.43.0.tgz",
+ "integrity": "sha512-jpsbcD0x6AUvV7tyOlyvon0aUsQpF8W+7TpJntfCUWU1qaIKu2K34pMwQKSzQH8ORgUrGYY6pVIh1Pi8TNeteg==",
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
@@ -4234,12 +4234,12 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.1.tgz",
- "integrity": "sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.43.0.tgz",
+ "integrity": "sha512-BZ1WVe+QQ+igWal2tDbNg1j2HWUkAa+CVqdU79L4HP9izQY6CNhXfkNwd1SS4+sSZAP/EthI1uiCSY/+H0pROg==",
"dependencies": {
- "@typescript-eslint/types": "5.42.1",
- "@typescript-eslint/visitor-keys": "5.42.1",
+ "@typescript-eslint/types": "5.43.0",
+ "@typescript-eslint/visitor-keys": "5.43.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -4274,15 +4274,15 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.42.1.tgz",
- "integrity": "sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.43.0.tgz",
+ "integrity": "sha512-8nVpA6yX0sCjf7v/NDfeaOlyaIIqL7OaIGOWSPFqUKK59Gnumd3Wa+2l8oAaYO2lk0sO+SbWFWRSvhu8gLGv4A==",
"dependencies": {
"@types/json-schema": "^7.0.9",
"@types/semver": "^7.3.12",
- "@typescript-eslint/scope-manager": "5.42.1",
- "@typescript-eslint/types": "5.42.1",
- "@typescript-eslint/typescript-estree": "5.42.1",
+ "@typescript-eslint/scope-manager": "5.43.0",
+ "@typescript-eslint/types": "5.43.0",
+ "@typescript-eslint/typescript-estree": "5.43.0",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0",
"semver": "^7.3.7"
@@ -4333,11 +4333,11 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.1.tgz",
- "integrity": "sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.43.0.tgz",
+ "integrity": "sha512-icl1jNH/d18OVHLfcwdL3bWUKsBeIiKYTGxMJCoGe7xFht+E4QgzOqoWYrU8XSLJWhVw8nTacbm03v23J/hFTg==",
"dependencies": {
- "@typescript-eslint/types": "5.42.1",
+ "@typescript-eslint/types": "5.43.0",
"eslint-visitor-keys": "^3.3.0"
},
"engines": {
@@ -4645,9 +4645,9 @@
}
},
"node_modules/ajv-formats/node_modules/ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -4897,9 +4897,9 @@
}
},
"node_modules/axe-core": {
- "version": "4.5.1",
- "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.5.1.tgz",
- "integrity": "sha512-1exVbW0X1O/HSr/WMwnaweyqcWOgZgLiVxdLG34pvSQk4NlYQr9OUy0JLwuhFfuVNQzzqgH57eYzkFBCb3bIsQ==",
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.5.2.tgz",
+ "integrity": "sha512-u2MVsXfew5HBvjsczCv+xlwdNnB1oQR9HlAcsejZttNjKKSkeDNVwB1vMThIUIFI9GoT57Vtk8iQLwqOfAkboA==",
"engines": {
"node": ">=4"
}
@@ -5543,9 +5543,12 @@
}
},
"node_modules/ci-info": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz",
- "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw=="
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz",
+ "integrity": "sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==",
+ "engines": {
+ "node": ">=8"
+ }
},
"node_modules/cjs-module-lexer": {
"version": "1.2.2",
@@ -5778,9 +5781,9 @@
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
"node_modules/core-js": {
- "version": "3.26.0",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.0.tgz",
- "integrity": "sha512-+DkDrhoR4Y0PxDz6rurahuB+I45OsEUv8E1maPTB6OuHRohMMcznBq9TMpdpDMm/hUPob/mJJS3PqgbHpMTQgw==",
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.1.tgz",
+ "integrity": "sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
@@ -5788,9 +5791,9 @@
}
},
"node_modules/core-js-compat": {
- "version": "3.26.0",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.26.0.tgz",
- "integrity": "sha512-piOX9Go+Z4f9ZiBFLnZ5VrOpBl0h7IGCkiFUN11QTe6LjAvOT3ifL/5TdoizMh99hcGy5SoLyWbapIY/PIb/3A==",
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.26.1.tgz",
+ "integrity": "sha512-622/KzTudvXCDLRw70iHW4KKs1aGpcRcowGWyYJr2DEBfRrd6hNJybxSWJFuZYD4ma86xhrwDDHxmDaIq4EA8A==",
"dependencies": {
"browserslist": "^4.21.4"
},
@@ -5800,9 +5803,9 @@
}
},
"node_modules/core-js-pure": {
- "version": "3.26.0",
- "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.26.0.tgz",
- "integrity": "sha512-LiN6fylpVBVwT8twhhluD9TzXmZQQsr2I2eIKtWNbZI1XMfBT7CV18itaN6RA7EtQd/SDdRx/wzvAShX2HvhQA==",
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.26.1.tgz",
+ "integrity": "sha512-VVXcDpp/xJ21KdULRq/lXdLzQAtX7+37LzpyfFM973il0tWSsDEoyzG38G14AjTpK9VTfiNM9jnFauq/CpaWGQ==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
@@ -5815,9 +5818,9 @@
"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==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+ "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
"dependencies": {
"@types/parse-json": "^4.0.0",
"import-fresh": "^3.2.1",
@@ -5904,18 +5907,18 @@
}
},
"node_modules/css-loader": {
- "version": "6.7.1",
- "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz",
- "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==",
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.2.tgz",
+ "integrity": "sha512-oqGbbVcBJkm8QwmnNzrFrWTnudnRZC+1eXikLJl0n4ljcfotgRifpg2a1lKy8jTrc4/d9A/ap1GFq1jDKG7J+Q==",
"dependencies": {
"icss-utils": "^5.1.0",
- "postcss": "^8.4.7",
+ "postcss": "^8.4.18",
"postcss-modules-extract-imports": "^3.0.0",
"postcss-modules-local-by-default": "^4.0.0",
"postcss-modules-scope": "^3.0.0",
"postcss-modules-values": "^4.0.0",
"postcss-value-parser": "^4.2.0",
- "semver": "^7.3.5"
+ "semver": "^7.3.8"
},
"engines": {
"node": ">= 12.13.0"
@@ -5980,9 +5983,9 @@
}
},
"node_modules/css-minimizer-webpack-plugin/node_modules/ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -7302,9 +7305,9 @@
}
},
"node_modules/eslint-webpack-plugin/node_modules/ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -10222,9 +10225,9 @@
}
},
"node_modules/jest-pnp-resolver": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz",
- "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
"engines": {
"node": ">=6"
},
@@ -11265,9 +11268,9 @@
}
},
"node_modules/js-base64": {
- "version": "3.7.2",
- "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.2.tgz",
- "integrity": "sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ=="
+ "version": "3.7.3",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.3.tgz",
+ "integrity": "sha512-PAr6Xg2jvd7MCR6Ld9Jg3BmTcjYsHEBx1VlwEwULb/qowPf5VD9kEMagj23Gm7JRnSvE/Da/57nChZjnvL8v6A=="
},
"node_modules/js-sdsl": {
"version": "4.1.5",
@@ -11512,9 +11515,9 @@
}
},
"node_modules/loader-utils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz",
- "integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+ "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dependencies": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
@@ -11642,9 +11645,9 @@
}
},
"node_modules/memfs": {
- "version": "3.4.10",
- "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.10.tgz",
- "integrity": "sha512-0bCUP+L79P4am30yP1msPzApwuMQG23TjwlwdHeEV5MxioDR1a0AgB0T9FfggU52eJuDCq8WVwb5ekznFyWiTQ==",
+ "version": "3.4.11",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.11.tgz",
+ "integrity": "sha512-GvsCITGAyDCxxsJ+X6prJexFQEhOCJaIlUbsAvjzSI5o5O7j2dle3jWvz5Z5aOdpOxW6ol3vI1+0ut+641F1+w==",
"dependencies": {
"fs-monkey": "^1.0.3"
},
@@ -11729,9 +11732,9 @@
}
},
"node_modules/mini-css-extract-plugin": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz",
- "integrity": "sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg==",
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.0.tgz",
+ "integrity": "sha512-auqtVo8KhTScMsba7MbijqZTfibbXiBNlPAQbsVt7enQfcDYLdgG57eGxMqwVU3mfeWANY4F1wUg+rMF+ycZgw==",
"dependencies": {
"schema-utils": "^4.0.0"
},
@@ -11747,9 +11750,9 @@
}
},
"node_modules/mini-css-extract-plugin/node_modules/ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -12495,9 +12498,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz",
- "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==",
+ "version": "8.4.19",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz",
+ "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==",
"funding": [
{
"type": "opencollective",
@@ -13435,11 +13438,11 @@
}
},
"node_modules/postcss-preset-env": {
- "version": "7.8.2",
- "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.2.tgz",
- "integrity": "sha512-rSMUEaOCnovKnwc5LvBDHUDzpGP+nrUeWZGWt9M72fBvckCi45JmnJigUr4QG4zZeOHmOCNCZnd2LKDvP++ZuQ==",
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz",
+ "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==",
"dependencies": {
- "@csstools/postcss-cascade-layers": "^1.1.0",
+ "@csstools/postcss-cascade-layers": "^1.1.1",
"@csstools/postcss-color-function": "^1.1.1",
"@csstools/postcss-font-format-keywords": "^1.0.1",
"@csstools/postcss-hwb-function": "^1.0.2",
@@ -13453,19 +13456,19 @@
"@csstools/postcss-text-decoration-shorthand": "^1.0.0",
"@csstools/postcss-trigonometric-functions": "^1.0.2",
"@csstools/postcss-unset-value": "^1.0.2",
- "autoprefixer": "^10.4.11",
- "browserslist": "^4.21.3",
+ "autoprefixer": "^10.4.13",
+ "browserslist": "^4.21.4",
"css-blank-pseudo": "^3.0.3",
"css-has-pseudo": "^3.0.4",
"css-prefers-color-scheme": "^6.0.3",
- "cssdb": "^7.0.1",
+ "cssdb": "^7.1.0",
"postcss-attribute-case-insensitive": "^5.0.2",
"postcss-clamp": "^4.1.0",
"postcss-color-functional-notation": "^4.2.4",
"postcss-color-hex-alpha": "^8.0.4",
"postcss-color-rebeccapurple": "^7.1.1",
"postcss-custom-media": "^8.0.2",
- "postcss-custom-properties": "^12.1.9",
+ "postcss-custom-properties": "^12.1.10",
"postcss-custom-selectors": "^6.0.3",
"postcss-dir-pseudo-class": "^6.0.5",
"postcss-double-position-gradients": "^3.1.2",
@@ -14032,9 +14035,9 @@
}
},
"node_modules/react-dev-utils/node_modules/loader-utils": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz",
- "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==",
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz",
+ "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==",
"engines": {
"node": ">= 12.13.0"
}
@@ -14348,16 +14351,16 @@
}
},
"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==",
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.2.tgz",
+ "integrity": "sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw==",
"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"
+ "unicode-match-property-value-ecmascript": "^2.1.0"
},
"engines": {
"node": ">=4"
@@ -15500,9 +15503,9 @@
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
},
"node_modules/tailwindcss": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.2.tgz",
- "integrity": "sha512-c2GtSdqg+harR4QeoTmex0Ngfg8IIHNeLQH5yr2B9uZbZR1Xt1rYbjWOWTcj3YLTZhrmZnPowoQDbSRFyZHQ5Q==",
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz",
+ "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==",
"dependencies": {
"arg": "^5.0.2",
"chokidar": "^3.5.3",
@@ -15863,9 +15866,9 @@
}
},
"node_modules/typescript": {
- "version": "4.8.4",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
- "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
+ "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",
@@ -15910,9 +15913,9 @@
}
},
"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==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz",
+ "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==",
"engines": {
"node": ">=4"
}
@@ -16142,9 +16145,9 @@
}
},
"node_modules/webpack": {
- "version": "5.74.0",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz",
- "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==",
+ "version": "5.75.0",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz",
+ "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==",
"dependencies": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^0.0.51",
@@ -16210,9 +16213,9 @@
}
},
"node_modules/webpack-dev-middleware/node_modules/ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -16313,9 +16316,9 @@
}
},
"node_modules/webpack-dev-server/node_modules/ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -16631,9 +16634,9 @@
}
},
"node_modules/workbox-build/node_modules/ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -19056,14 +19059,14 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A=="
},
"@mui/base": {
- "version": "5.0.0-alpha.105",
- "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.105.tgz",
- "integrity": "sha512-4IPBcJQIgVVXQvN6DQMoCHed52GBtwSqYs0jD0dDcMR3o76AodQtpEeWFz3p7mJoc6f/IHBl9U6jEfL1r/kM4g==",
+ "version": "5.0.0-alpha.106",
+ "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.106.tgz",
+ "integrity": "sha512-xJQQtwPCPwr6hGWTBdvDwHYwExn3Bw7nPQkN8Fuz8kHpZqoMVWQvvaFS557AIkkI2AFLV3DxVIMjbCvrIntBWg==",
"requires": {
- "@babel/runtime": "^7.19.0",
+ "@babel/runtime": "^7.20.1",
"@emotion/is-prop-valid": "^1.2.0",
- "@mui/types": "^7.2.0",
- "@mui/utils": "^5.10.9",
+ "@mui/types": "^7.2.1",
+ "@mui/utils": "^5.10.14",
"@popperjs/core": "^2.11.6",
"clsx": "^1.2.1",
"prop-types": "^15.8.1",
@@ -19071,29 +19074,29 @@
}
},
"@mui/core-downloads-tracker": {
- "version": "5.10.13",
- "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.13.tgz",
- "integrity": "sha512-zWkWPV/SaNdsIdxAWiuVGZ+Ue3BkfSIlU/BFIrJmuUcwiIa7gQsbI/DOpj1KzLvqZhdEe2wC1aG4nCHfzgc1Hg=="
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.14.tgz",
+ "integrity": "sha512-qLgIJNOR9Dre8JiZ/neVzOf4jf88J6YtOkQqugtMrleLjbfRVUSS4LWl9CSOjNq76quYdmYWnSDgfQqOooT2cQ=="
},
"@mui/icons-material": {
- "version": "5.10.9",
- "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.10.9.tgz",
- "integrity": "sha512-sqClXdEM39WKQJOQ0ZCPTptaZgqwibhj2EFV9N0v7BU1PO8y4OcX/a2wIQHn4fNuDjIZktJIBrmU23h7aqlGgg==",
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.10.14.tgz",
+ "integrity": "sha512-qtH60slQa+7MZRn6kyui8rKuoGDglPqaHX+pzBKNvd8JCOlrnfY5DmGGDdToTXyXl8xJ8nhANZbrbpg7UVKq/Q==",
"requires": {
- "@babel/runtime": "^7.19.0"
+ "@babel/runtime": "^7.20.1"
}
},
"@mui/material": {
- "version": "5.10.13",
- "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.10.13.tgz",
- "integrity": "sha512-TkkT1rNc0/hhL4/+zv4gYcA6egNWBH/1Tz+azoTnQIUdZ32fgwFI2pFX2KVJNTt30xnLznxDWtTv7ilmJQ52xw==",
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.10.14.tgz",
+ "integrity": "sha512-HWzKVAykePMx54WtxVwZyL1W4k3xlHYIqwMw0CaXAvgB3UE9yjABZuuGr8vG5Z6CSNWamzd+s1x8u7pQPFl9og==",
"requires": {
- "@babel/runtime": "^7.19.0",
- "@mui/base": "5.0.0-alpha.105",
- "@mui/core-downloads-tracker": "^5.10.13",
- "@mui/system": "^5.10.13",
- "@mui/types": "^7.2.0",
- "@mui/utils": "^5.10.9",
+ "@babel/runtime": "^7.20.1",
+ "@mui/base": "5.0.0-alpha.106",
+ "@mui/core-downloads-tracker": "^5.10.14",
+ "@mui/system": "^5.10.14",
+ "@mui/types": "^7.2.1",
+ "@mui/utils": "^5.10.14",
"@types/react-transition-group": "^4.4.5",
"clsx": "^1.2.1",
"csstype": "^3.1.1",
@@ -19103,53 +19106,53 @@
}
},
"@mui/private-theming": {
- "version": "5.10.9",
- "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.10.9.tgz",
- "integrity": "sha512-BN7/CnsVPVyBaQpDTij4uV2xGYHHHhOgpdxeYLlIu+TqnsVM7wUeF+37kXvHovxM6xmL5qoaVUD98gDC0IZnHg==",
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.10.14.tgz",
+ "integrity": "sha512-3aIBe8WK65CwAPDY8nB11hYnzE1CZMymi76UnaFrA/DdGDwl5Y8F6uB+StKrkVmsqF1po7Mp2odqVkHj320gXw==",
"requires": {
- "@babel/runtime": "^7.19.0",
- "@mui/utils": "^5.10.9",
+ "@babel/runtime": "^7.20.1",
+ "@mui/utils": "^5.10.14",
"prop-types": "^15.8.1"
}
},
"@mui/styled-engine": {
- "version": "5.10.8",
- "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.10.8.tgz",
- "integrity": "sha512-w+y8WI18EJV6zM/q41ug19cE70JTeO6sWFsQ7tgePQFpy6ToCVPh0YLrtqxUZXSoMStW5FMw0t9fHTFAqPbngw==",
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.10.14.tgz",
+ "integrity": "sha512-bgKdM57ExogWpIfhL/ngSlzF4FhbH00vYF+Y5VALTob4uslFqje0xzoWmbfcCn4cZt2NXxZJIwhsq4vzo5itlw==",
"requires": {
- "@babel/runtime": "^7.19.0",
- "@emotion/cache": "^11.10.3",
+ "@babel/runtime": "^7.20.1",
+ "@emotion/cache": "^11.10.5",
"csstype": "^3.1.1",
"prop-types": "^15.8.1"
}
},
"@mui/system": {
- "version": "5.10.13",
- "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.10.13.tgz",
- "integrity": "sha512-Xzx26Asu5fVlm0ucm+gnJmeX4Y1isrpVDvqxX4yJaOT7Fzmd8Lfq9ih3QMfZajns5LMtUiOuCQlVFRtUG5IY7A==",
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.10.14.tgz",
+ "integrity": "sha512-2de7XCjRb1j8Od0Stmo0LwFMLpOMNT4wzfINuExXI1TVSuyxXIXUxiC5FEgJW3GMvf/a7SUR8VOiMoKlKWzukw==",
"requires": {
- "@babel/runtime": "^7.19.0",
- "@mui/private-theming": "^5.10.9",
- "@mui/styled-engine": "^5.10.8",
- "@mui/types": "^7.2.0",
- "@mui/utils": "^5.10.9",
+ "@babel/runtime": "^7.20.1",
+ "@mui/private-theming": "^5.10.14",
+ "@mui/styled-engine": "^5.10.14",
+ "@mui/types": "^7.2.1",
+ "@mui/utils": "^5.10.14",
"clsx": "^1.2.1",
"csstype": "^3.1.1",
"prop-types": "^15.8.1"
}
},
"@mui/types": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.0.tgz",
- "integrity": "sha512-lGXtFKe5lp3UxTBGqKI1l7G8sE2xBik8qCfrLHD5olwP/YU0/ReWoWT7Lp1//ri32dK39oPMrJN8TgbkCSbsNA==",
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.1.tgz",
+ "integrity": "sha512-c5mSM7ivD8EsqK6HUi9hQPr5V7TJ/IRThUQ9nWNYPdhCGriTSQV4vL6DflT99LkM+wLiIS1rVjphpEWxERep7A==",
"requires": {}
},
"@mui/utils": {
- "version": "5.10.9",
- "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.10.9.tgz",
- "integrity": "sha512-2tdHWrq3+WCy+G6TIIaFx3cg7PorXZ71P375ExuX61od1NOAJP1mK90VxQ8N4aqnj2vmO3AQDkV4oV2Ktvt4bA==",
+ "version": "5.10.14",
+ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.10.14.tgz",
+ "integrity": "sha512-12p59+wDZpA++XVJmKwqsZmrA1nmUQ5d0a1yQWtcDjxNyER1EDzozYN/db+FY2i5ceQh2TynPTEwGms2mXDwFg==",
"requires": {
- "@babel/runtime": "^7.19.0",
+ "@babel/runtime": "^7.20.1",
"@types/prop-types": "^15.7.5",
"@types/react-is": "^16.7.1 || ^17.0.0",
"prop-types": "^15.8.1",
@@ -19204,9 +19207,9 @@
}
},
"@pmmmwh/react-refresh-webpack-plugin": {
- "version": "0.5.8",
- "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.8.tgz",
- "integrity": "sha512-wxXRwf+IQ6zvHSJZ+5T2RQNEsq+kx4jKRXfFvdt3nBIUzJUAvXEFsUeoaohDe/Kr84MTjGwcuIUPNcstNJORsA==",
+ "version": "0.5.9",
+ "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.9.tgz",
+ "integrity": "sha512-7QV4cqUwhkDIHpMAZ9mestSJ2DMIotVTbOUwbiudhjCRTAWWKIaBecELiEM2LT3AHFeOAaHIcFu4dbXjX+9GBA==",
"requires": {
"ansi-html-community": "^0.0.8",
"common-path-prefix": "^3.0.0",
@@ -19214,7 +19217,7 @@
"error-stack-parser": "^2.0.6",
"find-up": "^5.0.0",
"html-entities": "^2.1.0",
- "loader-utils": "^2.0.0",
+ "loader-utils": "^2.0.3",
"schema-utils": "^3.0.0",
"source-map": "^0.7.3"
},
@@ -19753,13 +19756,13 @@
"integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA=="
},
"@typescript-eslint/eslint-plugin": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.42.1.tgz",
- "integrity": "sha512-LyR6x784JCiJ1j6sH5Y0K6cdExqCCm8DJUTcwG5ThNXJj/G8o5E56u5EdG4SLy+bZAwZBswC+GYn3eGdttBVCg==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.43.0.tgz",
+ "integrity": "sha512-wNPzG+eDR6+hhW4yobEmpR36jrqqQv1vxBq5LJO3fBAktjkvekfr4BRl+3Fn1CM/A+s8/EiGUbOMDoYqWdbtXA==",
"requires": {
- "@typescript-eslint/scope-manager": "5.42.1",
- "@typescript-eslint/type-utils": "5.42.1",
- "@typescript-eslint/utils": "5.42.1",
+ "@typescript-eslint/scope-manager": "5.43.0",
+ "@typescript-eslint/type-utils": "5.43.0",
+ "@typescript-eslint/utils": "5.43.0",
"debug": "^4.3.4",
"ignore": "^5.2.0",
"natural-compare-lite": "^1.4.0",
@@ -19779,56 +19782,56 @@
}
},
"@typescript-eslint/experimental-utils": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.42.1.tgz",
- "integrity": "sha512-qona75z2MLpeZADEuCet5Pwvh1g/0cWScEEDy43chuUPc4klgDiwz5hLFk5dHcjFEETSYQHRPYiiHKW24EMPjw==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.43.0.tgz",
+ "integrity": "sha512-WkT637CumTJbm/hRbFfnHBMgfUYTKr08LitVsD7gQId7bi6rnkx3pu3jac67lmp5ObW4MpJ9SNFZAIOUB/Qbsw==",
"requires": {
- "@typescript-eslint/utils": "5.42.1"
+ "@typescript-eslint/utils": "5.43.0"
}
},
"@typescript-eslint/parser": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.42.1.tgz",
- "integrity": "sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.43.0.tgz",
+ "integrity": "sha512-2iHUK2Lh7PwNUlhFxxLI2haSDNyXvebBO9izhjhMoDC+S3XI9qt2DGFUsiJ89m2k7gGYch2aEpYqV5F/+nwZug==",
"requires": {
- "@typescript-eslint/scope-manager": "5.42.1",
- "@typescript-eslint/types": "5.42.1",
- "@typescript-eslint/typescript-estree": "5.42.1",
+ "@typescript-eslint/scope-manager": "5.43.0",
+ "@typescript-eslint/types": "5.43.0",
+ "@typescript-eslint/typescript-estree": "5.43.0",
"debug": "^4.3.4"
}
},
"@typescript-eslint/scope-manager": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.42.1.tgz",
- "integrity": "sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.43.0.tgz",
+ "integrity": "sha512-XNWnGaqAtTJsUiZaoiGIrdJYHsUOd3BZ3Qj5zKp9w6km6HsrjPk/TGZv0qMTWyWj0+1QOqpHQ2gZOLXaGA9Ekw==",
"requires": {
- "@typescript-eslint/types": "5.42.1",
- "@typescript-eslint/visitor-keys": "5.42.1"
+ "@typescript-eslint/types": "5.43.0",
+ "@typescript-eslint/visitor-keys": "5.43.0"
}
},
"@typescript-eslint/type-utils": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.42.1.tgz",
- "integrity": "sha512-WWiMChneex5w4xPIX56SSnQQo0tEOy5ZV2dqmj8Z371LJ0E+aymWD25JQ/l4FOuuX+Q49A7pzh/CGIQflxMVXg==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.43.0.tgz",
+ "integrity": "sha512-K21f+KY2/VvYggLf5Pk4tgBOPs2otTaIHy2zjclo7UZGLyFH86VfUOm5iq+OtDtxq/Zwu2I3ujDBykVW4Xtmtg==",
"requires": {
- "@typescript-eslint/typescript-estree": "5.42.1",
- "@typescript-eslint/utils": "5.42.1",
+ "@typescript-eslint/typescript-estree": "5.43.0",
+ "@typescript-eslint/utils": "5.43.0",
"debug": "^4.3.4",
"tsutils": "^3.21.0"
}
},
"@typescript-eslint/types": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.42.1.tgz",
- "integrity": "sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA=="
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.43.0.tgz",
+ "integrity": "sha512-jpsbcD0x6AUvV7tyOlyvon0aUsQpF8W+7TpJntfCUWU1qaIKu2K34pMwQKSzQH8ORgUrGYY6pVIh1Pi8TNeteg=="
},
"@typescript-eslint/typescript-estree": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.42.1.tgz",
- "integrity": "sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.43.0.tgz",
+ "integrity": "sha512-BZ1WVe+QQ+igWal2tDbNg1j2HWUkAa+CVqdU79L4HP9izQY6CNhXfkNwd1SS4+sSZAP/EthI1uiCSY/+H0pROg==",
"requires": {
- "@typescript-eslint/types": "5.42.1",
- "@typescript-eslint/visitor-keys": "5.42.1",
+ "@typescript-eslint/types": "5.43.0",
+ "@typescript-eslint/visitor-keys": "5.43.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -19847,15 +19850,15 @@
}
},
"@typescript-eslint/utils": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.42.1.tgz",
- "integrity": "sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.43.0.tgz",
+ "integrity": "sha512-8nVpA6yX0sCjf7v/NDfeaOlyaIIqL7OaIGOWSPFqUKK59Gnumd3Wa+2l8oAaYO2lk0sO+SbWFWRSvhu8gLGv4A==",
"requires": {
"@types/json-schema": "^7.0.9",
"@types/semver": "^7.3.12",
- "@typescript-eslint/scope-manager": "5.42.1",
- "@typescript-eslint/types": "5.42.1",
- "@typescript-eslint/typescript-estree": "5.42.1",
+ "@typescript-eslint/scope-manager": "5.43.0",
+ "@typescript-eslint/types": "5.43.0",
+ "@typescript-eslint/typescript-estree": "5.43.0",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0",
"semver": "^7.3.7"
@@ -19886,11 +19889,11 @@
}
},
"@typescript-eslint/visitor-keys": {
- "version": "5.42.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.42.1.tgz",
- "integrity": "sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.43.0.tgz",
+ "integrity": "sha512-icl1jNH/d18OVHLfcwdL3bWUKsBeIiKYTGxMJCoGe7xFht+E4QgzOqoWYrU8XSLJWhVw8nTacbm03v23J/hFTg==",
"requires": {
- "@typescript-eslint/types": "5.42.1",
+ "@typescript-eslint/types": "5.43.0",
"eslint-visitor-keys": "^3.3.0"
}
},
@@ -20146,9 +20149,9 @@
},
"dependencies": {
"ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -20321,9 +20324,9 @@
}
},
"axe-core": {
- "version": "4.5.1",
- "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.5.1.tgz",
- "integrity": "sha512-1exVbW0X1O/HSr/WMwnaweyqcWOgZgLiVxdLG34pvSQk4NlYQr9OUy0JLwuhFfuVNQzzqgH57eYzkFBCb3bIsQ=="
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.5.2.tgz",
+ "integrity": "sha512-u2MVsXfew5HBvjsczCv+xlwdNnB1oQR9HlAcsejZttNjKKSkeDNVwB1vMThIUIFI9GoT57Vtk8iQLwqOfAkboA=="
},
"axobject-query": {
"version": "2.2.0",
@@ -20802,9 +20805,9 @@
"integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg=="
},
"ci-info": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz",
- "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw=="
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz",
+ "integrity": "sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w=="
},
"cjs-module-lexer": {
"version": "1.2.2",
@@ -20998,22 +21001,22 @@
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
"core-js": {
- "version": "3.26.0",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.0.tgz",
- "integrity": "sha512-+DkDrhoR4Y0PxDz6rurahuB+I45OsEUv8E1maPTB6OuHRohMMcznBq9TMpdpDMm/hUPob/mJJS3PqgbHpMTQgw=="
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.1.tgz",
+ "integrity": "sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA=="
},
"core-js-compat": {
- "version": "3.26.0",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.26.0.tgz",
- "integrity": "sha512-piOX9Go+Z4f9ZiBFLnZ5VrOpBl0h7IGCkiFUN11QTe6LjAvOT3ifL/5TdoizMh99hcGy5SoLyWbapIY/PIb/3A==",
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.26.1.tgz",
+ "integrity": "sha512-622/KzTudvXCDLRw70iHW4KKs1aGpcRcowGWyYJr2DEBfRrd6hNJybxSWJFuZYD4ma86xhrwDDHxmDaIq4EA8A==",
"requires": {
"browserslist": "^4.21.4"
}
},
"core-js-pure": {
- "version": "3.26.0",
- "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.26.0.tgz",
- "integrity": "sha512-LiN6fylpVBVwT8twhhluD9TzXmZQQsr2I2eIKtWNbZI1XMfBT7CV18itaN6RA7EtQd/SDdRx/wzvAShX2HvhQA=="
+ "version": "3.26.1",
+ "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.26.1.tgz",
+ "integrity": "sha512-VVXcDpp/xJ21KdULRq/lXdLzQAtX7+37LzpyfFM973il0tWSsDEoyzG38G14AjTpK9VTfiNM9jnFauq/CpaWGQ=="
},
"core-util-is": {
"version": "1.0.3",
@@ -21021,9 +21024,9 @@
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"cosmiconfig": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz",
- "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+ "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
"requires": {
"@types/parse-json": "^4.0.0",
"import-fresh": "^3.2.1",
@@ -21078,18 +21081,18 @@
}
},
"css-loader": {
- "version": "6.7.1",
- "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz",
- "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==",
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.2.tgz",
+ "integrity": "sha512-oqGbbVcBJkm8QwmnNzrFrWTnudnRZC+1eXikLJl0n4ljcfotgRifpg2a1lKy8jTrc4/d9A/ap1GFq1jDKG7J+Q==",
"requires": {
"icss-utils": "^5.1.0",
- "postcss": "^8.4.7",
+ "postcss": "^8.4.18",
"postcss-modules-extract-imports": "^3.0.0",
"postcss-modules-local-by-default": "^4.0.0",
"postcss-modules-scope": "^3.0.0",
"postcss-modules-values": "^4.0.0",
"postcss-value-parser": "^4.2.0",
- "semver": "^7.3.5"
+ "semver": "^7.3.8"
},
"dependencies": {
"semver": {
@@ -21116,9 +21119,9 @@
},
"dependencies": {
"ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -22159,9 +22162,9 @@
},
"dependencies": {
"ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -24172,9 +24175,9 @@
}
},
"jest-pnp-resolver": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz",
- "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
"requires": {}
},
"jest-regex-util": {
@@ -24938,9 +24941,9 @@
}
},
"js-base64": {
- "version": "3.7.2",
- "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.2.tgz",
- "integrity": "sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ=="
+ "version": "3.7.3",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.3.tgz",
+ "integrity": "sha512-PAr6Xg2jvd7MCR6Ld9Jg3BmTcjYsHEBx1VlwEwULb/qowPf5VD9kEMagj23Gm7JRnSvE/Da/57nChZjnvL8v6A=="
},
"js-sdsl": {
"version": "4.1.5",
@@ -25126,9 +25129,9 @@
"integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg=="
},
"loader-utils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.3.tgz",
- "integrity": "sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+ "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
@@ -25232,9 +25235,9 @@
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
},
"memfs": {
- "version": "3.4.10",
- "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.10.tgz",
- "integrity": "sha512-0bCUP+L79P4am30yP1msPzApwuMQG23TjwlwdHeEV5MxioDR1a0AgB0T9FfggU52eJuDCq8WVwb5ekznFyWiTQ==",
+ "version": "3.4.11",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.11.tgz",
+ "integrity": "sha512-GvsCITGAyDCxxsJ+X6prJexFQEhOCJaIlUbsAvjzSI5o5O7j2dle3jWvz5Z5aOdpOxW6ol3vI1+0ut+641F1+w==",
"requires": {
"fs-monkey": "^1.0.3"
}
@@ -25292,17 +25295,17 @@
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
},
"mini-css-extract-plugin": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz",
- "integrity": "sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg==",
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.0.tgz",
+ "integrity": "sha512-auqtVo8KhTScMsba7MbijqZTfibbXiBNlPAQbsVt7enQfcDYLdgG57eGxMqwVU3mfeWANY4F1wUg+rMF+ycZgw==",
"requires": {
"schema-utils": "^4.0.0"
},
"dependencies": {
"ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -25831,9 +25834,9 @@
}
},
"postcss": {
- "version": "8.4.18",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz",
- "integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==",
+ "version": "8.4.19",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz",
+ "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==",
"requires": {
"nanoid": "^3.3.4",
"picocolors": "^1.0.0",
@@ -26328,11 +26331,11 @@
}
},
"postcss-preset-env": {
- "version": "7.8.2",
- "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.2.tgz",
- "integrity": "sha512-rSMUEaOCnovKnwc5LvBDHUDzpGP+nrUeWZGWt9M72fBvckCi45JmnJigUr4QG4zZeOHmOCNCZnd2LKDvP++ZuQ==",
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz",
+ "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==",
"requires": {
- "@csstools/postcss-cascade-layers": "^1.1.0",
+ "@csstools/postcss-cascade-layers": "^1.1.1",
"@csstools/postcss-color-function": "^1.1.1",
"@csstools/postcss-font-format-keywords": "^1.0.1",
"@csstools/postcss-hwb-function": "^1.0.2",
@@ -26346,19 +26349,19 @@
"@csstools/postcss-text-decoration-shorthand": "^1.0.0",
"@csstools/postcss-trigonometric-functions": "^1.0.2",
"@csstools/postcss-unset-value": "^1.0.2",
- "autoprefixer": "^10.4.11",
- "browserslist": "^4.21.3",
+ "autoprefixer": "^10.4.13",
+ "browserslist": "^4.21.4",
"css-blank-pseudo": "^3.0.3",
"css-has-pseudo": "^3.0.4",
"css-prefers-color-scheme": "^6.0.3",
- "cssdb": "^7.0.1",
+ "cssdb": "^7.1.0",
"postcss-attribute-case-insensitive": "^5.0.2",
"postcss-clamp": "^4.1.0",
"postcss-color-functional-notation": "^4.2.4",
"postcss-color-hex-alpha": "^8.0.4",
"postcss-color-rebeccapurple": "^7.1.1",
"postcss-custom-media": "^8.0.2",
- "postcss-custom-properties": "^12.1.9",
+ "postcss-custom-properties": "^12.1.10",
"postcss-custom-selectors": "^6.0.3",
"postcss-dir-pseudo-class": "^6.0.5",
"postcss-double-position-gradients": "^3.1.2",
@@ -26762,9 +26765,9 @@
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"loader-utils": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz",
- "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ=="
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz",
+ "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw=="
},
"supports-color": {
"version": "7.2.0",
@@ -26991,16 +26994,16 @@
"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg=="
},
"regexpu-core": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.1.tgz",
- "integrity": "sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ==",
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.2.tgz",
+ "integrity": "sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw==",
"requires": {
"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"
+ "unicode-match-property-value-ecmascript": "^2.1.0"
}
},
"regjsgen": {
@@ -27854,9 +27857,9 @@
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
},
"tailwindcss": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.2.tgz",
- "integrity": "sha512-c2GtSdqg+harR4QeoTmex0Ngfg8IIHNeLQH5yr2B9uZbZR1Xt1rYbjWOWTcj3YLTZhrmZnPowoQDbSRFyZHQ5Q==",
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz",
+ "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==",
"requires": {
"arg": "^5.0.2",
"chokidar": "^3.5.3",
@@ -28120,9 +28123,9 @@
}
},
"typescript": {
- "version": "4.8.4",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
- "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
+ "version": "4.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
+ "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
"peer": true
},
"unbox-primitive": {
@@ -28151,9 +28154,9 @@
}
},
"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=="
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz",
+ "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA=="
},
"unicode-property-aliases-ecmascript": {
"version": "2.1.0",
@@ -28319,9 +28322,9 @@
"integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w=="
},
"webpack": {
- "version": "5.74.0",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz",
- "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==",
+ "version": "5.75.0",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz",
+ "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==",
"requires": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^0.0.51",
@@ -28383,9 +28386,9 @@
},
"dependencies": {
"ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -28456,9 +28459,9 @@
},
"dependencies": {
"ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
@@ -28684,9 +28687,9 @@
}
},
"ajv": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
- "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
diff --git a/web/public/static/langs/sv.json b/web/public/static/langs/sv.json
new file mode 100644
index 00000000..e857ed2b
--- /dev/null
+++ b/web/public/static/langs/sv.json
@@ -0,0 +1,45 @@
+{
+ "action_bar_settings": "Inställningar",
+ "action_bar_send_test_notification": "Skicka test notis",
+ "action_bar_toggle_action_menu": "Öppna/stäng åtgärdsmeny",
+ "message_bar_type_message": "Skriv ett meddelande här",
+ "message_bar_error_publishing": "Fel vid publicering av notis",
+ "message_bar_show_dialog": "Visa publicerings dialog",
+ "message_bar_publish": "Publicera meddelande",
+ "nav_topics_title": "Prenumererade kategorier",
+ "nav_button_all_notifications": "Alla notiser",
+ "nav_button_documentation": "Dokumentation",
+ "nav_button_publish_message": "Publicera notis",
+ "nav_button_subscribe": "Prenumerera på kategori",
+ "alert_grant_title": "Notiser är avstängda",
+ "alert_grant_button": "Bevilja nu",
+ "alert_not_supported_title": "Notiser stöds inte",
+ "notifications_list": "Notis-lista",
+ "notifications_list_item": "Notis",
+ "notifications_delete": "Radera",
+ "notifications_copied_to_clipboard": "Kopierat till urklipp",
+ "notifications_tags": "Taggar",
+ "notifications_new_indicator": "Ny notis",
+ "notifications_attachment_copy_url_title": "Kopiera bifogad URL till urklipp",
+ "notifications_attachment_copy_url_button": "Kopiera URL",
+ "notifications_attachment_open_title": "Gå till {{url}}",
+ "notifications_attachment_open_button": "Öppna bilagan",
+ "notifications_attachment_link_expired": "Nedladdningslänk utgått",
+ "notifications_priority_x": "Prioritet {{priority}}",
+ "action_bar_show_menu": "Visa meny",
+ "action_bar_logo_alt": "ntfy logga",
+ "action_bar_unsubscribe": "Avprenumerera",
+ "action_bar_toggle_mute": "Tysta/aktivera notiser",
+ "action_bar_clear_notifications": "Rensa alla notiser",
+ "nav_button_connecting": "ansluter",
+ "notifications_attachment_image": "Bifogad bild",
+ "nav_button_settings": "Inställningar",
+ "nav_button_muted": "Notiser tystade",
+ "notifications_attachment_link_expires": "länken utgår {{date}}",
+ "notifications_attachment_file_image": "bild fil",
+ "notifications_attachment_file_audio": "ljud fil",
+ "alert_grant_description": "Ge din webbläsare behörighet att visa skrivbordsnotiser.",
+ "alert_not_supported_description": "Notiser stöds inte i din webbläsare.",
+ "notifications_mark_read": "Markera som läst",
+ "notifications_attachment_file_video": "video fil"
+}