From 1ab984d0ddba4e12a6c39adda795108fd7edeb68 Mon Sep 17 00:00:00 2001
From: Lingfei Song <82314+madcat@users.noreply.github.com>
Date: Thu, 11 Apr 2024 12:39:52 +0700
Subject: [PATCH 01/16] add web
---
client/.dockerignore | 14 +
client/.gitignore | 4 +
client/Dockerfile.api | 16 +
client/Dockerfile.web | 31 +
client/backend/requirements.txt | 3 +-
client/backend/tasks.sh | 3 +-
client/compose.yaml | 21 +
client/pb/CHANGELOG.md | 936 -----
client/pb/LICENSE.md | 17 -
client/pb/pb_hooks/main.pb.js | 2 +-
client/web/.env.development | 2 +
client/web/.env.production | 2 +
client/web/.eslintrc.cjs | 13 +
client/web/.gitignore | 24 +
client/web/README.md | 6 +
client/web/components.json | 17 +
client/web/index.html | 13 +
client/web/package.json | 56 +
client/web/pnpm-lock.yaml | 3374 +++++++++++++++++
client/web/postcss.config.js | 6 +
client/web/public/vite.svg | 1 +
client/web/src/App.css | 13 +
client/web/src/App.jsx | 54 +
client/web/src/assets/react.svg | 1 +
client/web/src/components/article-list.jsx | 33 +
client/web/src/components/layout/step.jsx | 21 +
client/web/src/components/screen/articles.jsx | 74 +
client/web/src/components/screen/insights.jsx | 160 +
client/web/src/components/screen/login.jsx | 82 +
client/web/src/components/screen/report.jsx | 98 +
client/web/src/components/screen/start.jsx | 58 +
client/web/src/components/screen/steps.jsx | 105 +
client/web/src/components/ui/accordion.jsx | 41 +
client/web/src/components/ui/banner.jsx | 9 +
.../web/src/components/ui/button-loading.jsx | 11 +
client/web/src/components/ui/button.jsx | 47 +
client/web/src/components/ui/form.jsx | 133 +
client/web/src/components/ui/input.jsx | 19 +
client/web/src/components/ui/label.jsx | 16 +
client/web/src/components/ui/textarea.jsx | 18 +
client/web/src/components/ui/toast.jsx | 82 +
client/web/src/components/ui/toaster.jsx | 33 +
client/web/src/components/ui/use-toast.js | 154 +
client/web/src/index.css | 82 +
client/web/src/lib/utils.js | 18 +
client/web/src/main.jsx | 10 +
client/web/src/store.js | 273 ++
client/web/tailwind.config.js | 77 +
client/web/tsconfig.json | 8 +
client/web/vite.config.js | 15 +
50 files changed, 5350 insertions(+), 956 deletions(-)
create mode 100644 client/.dockerignore
create mode 100644 client/.gitignore
create mode 100644 client/Dockerfile.api
create mode 100644 client/Dockerfile.web
create mode 100644 client/compose.yaml
delete mode 100644 client/pb/CHANGELOG.md
delete mode 100644 client/pb/LICENSE.md
create mode 100644 client/web/.env.development
create mode 100644 client/web/.env.production
create mode 100644 client/web/.eslintrc.cjs
create mode 100644 client/web/.gitignore
create mode 100644 client/web/README.md
create mode 100644 client/web/components.json
create mode 100644 client/web/index.html
create mode 100644 client/web/package.json
create mode 100644 client/web/pnpm-lock.yaml
create mode 100644 client/web/postcss.config.js
create mode 100644 client/web/public/vite.svg
create mode 100644 client/web/src/App.css
create mode 100644 client/web/src/App.jsx
create mode 100644 client/web/src/assets/react.svg
create mode 100644 client/web/src/components/article-list.jsx
create mode 100644 client/web/src/components/layout/step.jsx
create mode 100644 client/web/src/components/screen/articles.jsx
create mode 100644 client/web/src/components/screen/insights.jsx
create mode 100644 client/web/src/components/screen/login.jsx
create mode 100644 client/web/src/components/screen/report.jsx
create mode 100644 client/web/src/components/screen/start.jsx
create mode 100644 client/web/src/components/screen/steps.jsx
create mode 100644 client/web/src/components/ui/accordion.jsx
create mode 100644 client/web/src/components/ui/banner.jsx
create mode 100644 client/web/src/components/ui/button-loading.jsx
create mode 100644 client/web/src/components/ui/button.jsx
create mode 100644 client/web/src/components/ui/form.jsx
create mode 100644 client/web/src/components/ui/input.jsx
create mode 100644 client/web/src/components/ui/label.jsx
create mode 100644 client/web/src/components/ui/textarea.jsx
create mode 100644 client/web/src/components/ui/toast.jsx
create mode 100644 client/web/src/components/ui/toaster.jsx
create mode 100644 client/web/src/components/ui/use-toast.js
create mode 100644 client/web/src/index.css
create mode 100644 client/web/src/lib/utils.js
create mode 100644 client/web/src/main.jsx
create mode 100644 client/web/src/store.js
create mode 100644 client/web/tailwind.config.js
create mode 100644 client/web/tsconfig.json
create mode 100644 client/web/vite.config.js
diff --git a/client/.dockerignore b/client/.dockerignore
new file mode 100644
index 0000000..4d15359
--- /dev/null
+++ b/client/.dockerignore
@@ -0,0 +1,14 @@
+.git
+.vscode
+.dockerignore
+.gitignore
+.env
+config
+build
+web/dist
+web/node_modules
+docker-compose.yaml
+Dockerfile
+README.md
+backend/__pycache__
+backend/AWtest
\ No newline at end of file
diff --git a/client/.gitignore b/client/.gitignore
new file mode 100644
index 0000000..783ac3b
--- /dev/null
+++ b/client/.gitignore
@@ -0,0 +1,4 @@
+.env
+.venv/
+pb/pb_data/
+backend/AWtest/
\ No newline at end of file
diff --git a/client/Dockerfile.api b/client/Dockerfile.api
new file mode 100644
index 0000000..6e10a9b
--- /dev/null
+++ b/client/Dockerfile.api
@@ -0,0 +1,16 @@
+FROM python:3.10-slim
+
+RUN apt-get update && \
+ apt-get install -yq tzdata && \
+ ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
+ dpkg-reconfigure -f noninteractive tzdata
+
+WORKDIR /app
+
+COPY backend/requirements.txt requirements.txt
+RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
+
+COPY backend ./
+
+EXPOSE 7777
+CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7777"]
\ No newline at end of file
diff --git a/client/Dockerfile.web b/client/Dockerfile.web
new file mode 100644
index 0000000..d4ef67d
--- /dev/null
+++ b/client/Dockerfile.web
@@ -0,0 +1,31 @@
+FROM node:20-slim as builder
+
+WORKDIR /app
+
+COPY web ./
+RUN npm install -g pnpm
+RUN pnpm install
+RUN pnpm build
+
+
+FROM alpine:latest
+
+ARG PB_VERSION=0.21.1
+
+RUN apk add --no-cache unzip ca-certificates tzdata
+
+# download and unzip PocketBase
+ADD https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_linux_amd64.zip /tmp/pb.zip
+RUN unzip /tmp/pb.zip -d /pb/
+
+RUN mkdir -p /pb
+
+COPY ./pb/pb_migrations /pb/pb_migrations
+COPY ./pb/pb_hooks /pb/pb_hooks
+COPY --from=builder /app/dist /pb/pb_public
+
+WORKDIR /pb
+
+EXPOSE 8090
+
+CMD ["/pb/pocketbase", "serve", "--http=0.0.0.0:8090"]
diff --git a/client/backend/requirements.txt b/client/backend/requirements.txt
index 70b3b44..e2148b6 100644
--- a/client/backend/requirements.txt
+++ b/client/backend/requirements.txt
@@ -13,4 +13,5 @@ langsmith==0.0.77
faiss-cpu # for cpu-only environment
pocketbase==0.10.0
gne
-selenium
\ No newline at end of file
+selenium
+chardet
\ No newline at end of file
diff --git a/client/backend/tasks.sh b/client/backend/tasks.sh
index 8cbccf6..f3ea41d 100755
--- a/client/backend/tasks.sh
+++ b/client/backend/tasks.sh
@@ -1,3 +1,4 @@
+set -o allexport
source ../.env
-
+set +o allexport
python background_task.py
\ No newline at end of file
diff --git a/client/compose.yaml b/client/compose.yaml
new file mode 100644
index 0000000..88c0a7a
--- /dev/null
+++ b/client/compose.yaml
@@ -0,0 +1,21 @@
+services:
+ web:
+ build:
+ dockerfile: Dockerfile.web
+ ports:
+ - 8090:8090
+ # env_file:
+ # - .env
+ volumes:
+ - ./pb/pb_data:/pb/pb_data
+ # - ./${PROJECT_DIR}:/pb/${PROJECT_DIR}
+ api:
+ build:
+ dockerfile: Dockerfile.api
+ env_file:
+ - .env
+ ports:
+ - 7777:7777
+ volumes:
+ #- ./${PROJECT_DIR}:/app/${PROJECT_DIR}
+ - ${EMBEDDING_MODEL_PATH}:${EMBEDDING_MODEL_PATH}
diff --git a/client/pb/CHANGELOG.md b/client/pb/CHANGELOG.md
deleted file mode 100644
index 2e6ee75..0000000
--- a/client/pb/CHANGELOG.md
+++ /dev/null
@@ -1,936 +0,0 @@
-## v0.22.3
-
-- Fixed the z-index of the current admin dropdown on Safari ([#4492](https://github.com/pocketbase/pocketbase/issues/4492)).
-
-- Fixed `OnAfterApiError` debug log `nil` error reference ([#4498](https://github.com/pocketbase/pocketbase/issues/4498)).
-
-- Added the field name as part of the `@request.data.someRelField.*` join to handle the case when a collection has 2 or more relation fields pointing to the same place ([#4500](https://github.com/pocketbase/pocketbase/issues/4500)).
-
-- Updated Go deps and bumped the min Go version in the GitHub release action to Go 1.22.1 since it comes with [some security fixes](https://github.com/golang/go/issues?q=milestone%3AGo1.22.1).
-
-
-## v0.22.2
-
-- Fixed a small regression introduced with v0.22.0 that was causing some missing unknown fields to always return an error instead of applying the specific `nullifyMisingField` resolver option to the query.
-
-
-## v0.22.1
-
-- Fixed Admin UI record and collection panels not reinitializing properly on browser back/forward navigation ([#4462](https://github.com/pocketbase/pocketbase/issues/4462)).
-
-- Initialize `RecordAuthWithOAuth2Event.IsNewRecord` for the `OnRecordBeforeAuthWithOAuth2Request` hook ([#4437](https://github.com/pocketbase/pocketbase/discussions/4437)).
-
-- Added error checks to the autogenerated Go migrations ([#4448](https://github.com/pocketbase/pocketbase/issues/4448)).
-
-
-## v0.22.0
-
-- Added Planning Center OAuth2 provider ([#4393](https://github.com/pocketbase/pocketbase/pull/4393); thanks @alxjsn).
-
-- Admin UI improvements:
- - Autosync collection changes across multiple open browser tabs.
- - Fixed vertical image popup preview scrolling.
- - Added options to export a subset of collections.
- - Added option to import a subset of collections without deleting the others ([#3403](https://github.com/pocketbase/pocketbase/issues/3403)).
-
-- Added support for back/indirect relation `filter`/`sort` (single and multiple).
- The syntax to reference back relation fields is `yourCollection_via_yourRelField.*`.
- ⚠️ To avoid excessive joins, the nested relations resolver is now limited to max 6 level depth (the same as `expand`).
- _Note that in the future there will be also more advanced and granular options to specify a subset of the fields that are filterable/sortable._
-
-- Added support for multiple back/indirect relation `expand` and updated the keys to use the `_via_` reference syntax (`yourCollection_via_yourRelField`).
- _To minimize the breaking changes, the old parenthesis reference syntax (`yourCollection(yourRelField)`) will still continue to work but it is soft-deprecated and there will be a console log reminding you to change it to the new one._
-
-- ⚠️ Collections and fields are no longer allowed to have `_via_` in their name to avoid collisions with the back/indirect relation reference syntax.
-
-- Added `jsvm.Config.OnInit` optional config function to allow registering custom Go bindings to the JSVM.
-
-- Added `@request.context` rule field that can be used to apply a different set of constraints based on the API rule execution context.
- For example, to disallow user creation by an OAuth2 auth, you could set for the users Create API rule `@request.context != "oauth2"`.
- The currently supported `@request.context` values are:
- ```
- default
- realtime
- protectedFile
- oauth2
- ```
-
-- Adjusted the `cron.Start()` to start the ticker at the `00` second of the cron interval ([#4394](https://github.com/pocketbase/pocketbase/discussions/4394)).
- _Note that the cron format has only minute granularity and there is still no guarantee that the scheduled job will be always executed at the `00` second._
-
-- Fixed auto backups cron not reloading properly after app settings change ([#4431](https://github.com/pocketbase/pocketbase/discussions/4431)).
-
-- Upgraded to `aws-sdk-go-v2` and added special handling for GCS to workaround the previous [GCS headers signature issue](https://github.com/pocketbase/pocketbase/issues/2231) that we had with v2.
- _This should also fix the SVG/JSON zero response when using Cloudflare R2 ([#4287](https://github.com/pocketbase/pocketbase/issues/4287#issuecomment-1925168142), [#2068](https://github.com/pocketbase/pocketbase/discussions/2068), [#2952](https://github.com/pocketbase/pocketbase/discussions/2952))._
- _⚠️ If you are using S3 for uploaded files or backups, please verify that you have a green check in the Admin UI for your S3 configuration (I've tested the new version with GCS, MinIO, Cloudflare R2 and Wasabi)._
-
-- Added `:each` modifier support for `file` and `relation` type fields (_previously it was supported only for `select` type fields_).
-
-- Other minor improvements (updated the `ghupdate` plugin to use the configured executable name when printing to the console, fixed the error reporting of `admin update/delete` commands, etc.).
-
-
-## v0.21.3
-
-- Ignore the JS required validations for disabled OIDC providers ([#4322](https://github.com/pocketbase/pocketbase/issues/4322)).
-
-- Allow `HEAD` requests to the `/api/health` endpoint ([#4310](https://github.com/pocketbase/pocketbase/issues/4310)).
-
-- Fixed the `editor` field value when visualized inside the View collection preview panel.
-
-- Manually clear all TinyMCE events on editor removal (_workaround for [tinymce#9377](https://github.com/tinymce/tinymce/issues/9377)_).
-
-
-## v0.21.2
-
-- Fixed `@request.auth.*` initialization side-effect which caused the current authenticated user email to not being returned in the user auth response ([#2173](https://github.com/pocketbase/pocketbase/issues/2173#issuecomment-1932332038)).
- _The current authenticated user email should be accessible always no matter of the `emailVisibility` state._
-
-- Fixed `RecordUpsert.RemoveFiles` godoc example.
-
-- Bumped to `NumCPU()+2` the `thumbGenSem` limit as some users reported that it was too restrictive.
-
-
-## v0.21.1
-
-- Small fix for the Admin UI related to the _Settings > Sync_ menu not being visible even when the "Hide controls" toggle is off.
-
-
-## v0.21.0
-
-- Added Bitbucket OAuth2 provider ([#3948](https://github.com/pocketbase/pocketbase/pull/3948); thanks @aabajyan).
-
-- Mark user as verified on confirm password reset ([#4066](https://github.com/pocketbase/pocketbase/issues/4066)).
- _If the user email has changed after issuing the reset token (eg. updated by an admin), then the `verified` user state remains unchanged._
-
-- Added support for loading a serialized json payload for `multipart/form-data` requests using the special `@jsonPayload` key.
- _This is intended to be used primarily by the SDKs to resolve [js-sdk#274](https://github.com/pocketbase/js-sdk/issues/274)._
-
-- Added graceful OAuth2 redirect error handling ([#4177](https://github.com/pocketbase/pocketbase/issues/4177)).
- _Previously on redirect error we were returning directly a standard json error response. Now on redirect error we'll redirect to a generic OAuth2 failure screen (similar to the success one) and will attempt to auto close the OAuth2 popup._
- _The SDKs are also updated to handle the OAuth2 redirect error and it will be returned as Promise rejection of the `authWithOAuth2()` call._
-
-- Exposed `$apis.gzip()` and `$apis.bodyLimit(bytes)` middlewares to the JSVM.
-
-- Added `TestMailer.SentMessages` field that holds all sent test app emails until cleanup.
-
-- Optimized the cascade delete of records with multiple `relation` fields.
-
-- Updated the `serve` and `admin` commands error reporting.
-
-- Minor Admin UI improvements (reduced the min table row height, added option to duplicate fields, added new TinyMCE codesample plugin languages, hide the collection sync settings when the `Settings.Meta.HideControls` is enabled, etc.)
-
-
-## v0.20.7
-
-- Fixed the Admin UI auto indexes update when renaming fields with a common prefix ([#4160](https://github.com/pocketbase/pocketbase/issues/4160)).
-
-
-## v0.20.6
-
-- Fixed JSVM types generation for functions with omitted arg types ([#4145](https://github.com/pocketbase/pocketbase/issues/4145)).
-
-- Updated Go deps.
-
-
-## v0.20.5
-
-- Minor CSS fix for the Admin UI to prevent the searchbar within a popup from expanding too much and pushing the controls out of the visible area ([#4079](https://github.com/pocketbase/pocketbase/issues/4079#issuecomment-1876994116)).
-
-
-## v0.20.4
-
-- Small fix for a regression introduced with the recent `json` field changes that was causing View collection column expressions recognized as `json` to fail to resolve ([#4072](https://github.com/pocketbase/pocketbase/issues/4072)).
-
-
-## v0.20.3
-
-- Fixed the `json` field query comparisons to work correctly with plain JSON values like `null`, `bool` `number`, etc. ([#4068](https://github.com/pocketbase/pocketbase/issues/4068)).
- Since there are plans in the future to allow custom SQLite builds and also in some situations it may be useful to be able to distinguish `NULL` from `''`,
- for the `json` fields (and for any other future non-standard field) we no longer apply `COALESCE` by default, aka.:
- ```
- Dataset:
- 1) data: json(null)
- 2) data: json('')
-
- For the filter "data = null" only 1) will resolve to TRUE.
- For the filter "data = ''" only 2) will resolve to TRUE.
- ```
-
-- Minor Go tests improvements
- - Sorted the record cascade delete references to ensure that the delete operation will preserve the order of the fired events when running the tests.
- - Marked some of the tests as safe for parallel execution to speed up a little the GitHub action build times.
-
-
-## v0.20.2
-
-- Added `sleep(milliseconds)` JSVM binding.
- _It works the same way as Go `time.Sleep()`, aka. it pauses the goroutine where the JSVM code is running._
-
-- Fixed multi-line text paste in the Admin UI search bar ([#4022](https://github.com/pocketbase/pocketbase/discussions/4022)).
-
-- Fixed the monospace font loading in the Admin UI.
-
-- Fixed various reported docs and code comment typos.
-
-
-## v0.20.1
-
-- Added `--dev` flag and its accompanying `app.IsDev()` method (_in place of the previously removed `--debug`_) to assist during development ([#3918](https://github.com/pocketbase/pocketbase/discussions/3918)).
- The `--dev` flag prints in the console "everything" and more specifically:
- - the data DB SQL statements
- - all `app.Logger().*` logs (debug, info, warning, error, etc.), no matter of the logs persistence settings in the Admin UI
-
-- Minor Admin UI fixes:
- - Fixed the log `error` label text wrapping.
- - Added the log `referer` (_when it is from a different source_) and `details` labels in the logs listing.
- - Removed the blank current time entry from the logs chart because it was causing confusion when used with custom time ranges.
- - Updated the SQL syntax highlighter and keywords autocompletion in the Admin UI to recognize `CAST(x as bool)` expressions.
-
-- Replaced the default API tests timeout with a new `ApiScenario.Timeout` option ([#3930](https://github.com/pocketbase/pocketbase/issues/3930)).
- A negative or zero value means no tests timeout.
- If a single API test takes more than 3s to complete it will have a log message visible when the test fails or when `go test -v` flag is used.
-
-- Added timestamp at the beginning of the generated JSVM types file to avoid creating it everytime with the app startup.
-
-
-## v0.20.0
-
-- Added `expand`, `filter`, `fields`, custom query and headers parameters support for the realtime subscriptions.
- _Requires JS SDK v0.20.0+ or Dart SDK v0.17.0+._
-
- ```js
- // JS SDK v0.20.0
- pb.collection("example").subscribe("*", (e) => {
- ...
- }, {
- expand: "someRelField",
- filter: "status = 'active'",
- fields: "id,expand.someRelField.*:excerpt(100)",
- })
- ```
-
- ```dart
- // Dart SDK v0.17.0
- pb.collection("example").subscribe("*", (e) {
- ...
- },
- expand: "someRelField",
- filter: "status = 'active'",
- fields: "id,expand.someRelField.*:excerpt(100)",
- )
- ```
-
-- Generalized the logs to allow any kind of application logs, not just requests.
-
- The new `app.Logger()` implements the standard [`log/slog` interfaces](https://pkg.go.dev/log/slog) available with Go 1.21.
- ```
- // Go: https://pocketbase.io/docs/go-logging/
- app.Logger().Info("Example message", "total", 123, "details", "lorem ipsum...")
-
- // JS: https://pocketbase.io/docs/js-logging/
- $app.logger().info("Example message", "total", 123, "details", "lorem ipsum...")
- ```
-
- For better performance and to minimize blocking on hot paths, logs are currently written with
- debounce and on batches:
- - 3 seconds after the last debounced log write
- - when the batch threshold is reached (currently 200)
- - right before app termination to attempt saving everything from the existing logs queue
-
- Some notable log related changes:
-
- - ⚠️ Bumped the minimum required Go version to 1.21.
-
- - ⚠️ Removed `_requests` table in favor of the generalized `_logs`.
- _Note that existing logs will be deleted!_
-
- - ⚠️ Renamed the following `Dao` log methods:
- ```go
- Dao.RequestQuery(...) -> Dao.LogQuery(...)
- Dao.FindRequestById(...) -> Dao.FindLogById(...)
- Dao.RequestsStats(...) -> Dao.LogsStats(...)
- Dao.DeleteOldRequests(...) -> Dao.DeleteOldLogs(...)
- Dao.SaveRequest(...) -> Dao.SaveLog(...)
- ```
- - ⚠️ Removed `app.IsDebug()` and the `--debug` flag.
- This was done to avoid the confusion with the new logger and its debug severity level.
- If you want to store debug logs you can set `-4` as min log level from the Admin UI.
-
- - Refactored Admin UI Logs:
- - Added new logs table listing.
- - Added log settings option to toggle the IP logging for the activity logger.
- - Added log settings option to specify a minimum log level.
- - Added controls to export individual or bulk selected logs as json.
- - Other minor improvements and fixes.
-
-- Added new `filesystem/System.Copy(src, dest)` method to copy existing files from one location to another.
- _This is usually useful when duplicating records with `file` field(s) programmatically._
-
-- Added `filesystem.NewFileFromUrl(ctx, url)` helper method to construct a `*filesystem.BytesReader` file from the specified url.
-
-- OAuth2 related additions:
-
- - Added new `PKCE()` and `SetPKCE(enable)` OAuth2 methods to indicate whether the PKCE flow is supported or not.
- _The PKCE value is currently configurable from the UI only for the OIDC providers._
- _This was added to accommodate OIDC providers that may throw an error if unsupported PKCE params are submitted with the auth request (eg. LinkedIn; see [#3799](https://github.com/pocketbase/pocketbase/discussions/3799#discussioncomment-7640312))._
-
- - Added new `displayName` field for each `listAuthMethods()` OAuth2 provider item.
- _The value of the `displayName` property is currently configurable from the UI only for the OIDC providers._
-
- - Added `expiry` field to the OAuth2 user response containing the _optional_ expiration time of the OAuth2 access token ([#3617](https://github.com/pocketbase/pocketbase/discussions/3617)).
-
- - Allow a single OAuth2 user to be used for authentication in multiple auth collection.
- _⚠️ Because now you can have more than one external provider with `collectionId-provider-providerId` pair, `Dao.FindExternalAuthByProvider(provider, providerId)` method was removed in favour of the more generic `Dao.FindFirstExternalAuthByExpr(expr)`._
-
-- Added `onlyVerified` auth collection option to globally disallow authentication requests for unverified users.
-
-- Added support for single line comments (ex. `// your comment`) in the API rules and filter expressions.
-
-- Added support for specifying a collection alias in `@collection.someCollection:alias.*`.
-
-- Soft-deprecated and renamed `app.Cache()` with `app.Store()`.
-
-- Minor JSVM updates and fixes:
-
- - Updated `$security.parseUnverifiedJWT(token)` and `$security.parseJWT(token, key)` to return the token payload result as plain object.
-
- - Added `$apis.requireGuestOnly()` middleware JSVM binding ([#3896](https://github.com/pocketbase/pocketbase/issues/3896)).
-
-- Use `IS NOT` instead of `!=` as not-equal SQL query operator to handle the cases when comparing with nullable columns or expressions (eg. `json_extract` over `json` field).
- _Based on my local dataset I wasn't able to find a significant difference in the performance between the 2 operators, but if you stumble on a query that you think may be affected negatively by this, please report it and I'll test it further._
-
-- Added `MaxSize` `json` field option to prevent storing large json data in the db ([#3790](https://github.com/pocketbase/pocketbase/issues/3790)).
- _Existing `json` fields are updated with a system migration to have a ~2MB size limit (it can be adjusted from the Admin UI)._
-
-- Fixed negative string number normalization support for the `json` field type.
-
-- Trigger the `app.OnTerminate()` hook on `app.Restart()` call.
- _A new bool `IsRestart` field was also added to the `core.TerminateEvent` event._
-
-- Fixed graceful shutdown handling and speed up a little the app termination time.
-
-- Limit the concurrent thumbs generation to avoid high CPU and memory usage in spiky scenarios ([#3794](https://github.com/pocketbase/pocketbase/pull/3794); thanks @t-muehlberger).
- _Currently the max concurrent thumbs generation processes are limited to "total of logical process CPUs + 1"._
- _This is arbitrary chosen and may change in the future depending on the users feedback and usage patterns._
- _If you are experiencing OOM errors during large image thumb generations, especially in container environment, you can try defining the `GOMEMLIMIT=500MiB` env variable before starting the executable._
-
-- Slightly speed up (~10%) the thumbs generation by changing from cubic (`CatmullRom`) to bilinear (`Linear`) resampling filter (_the quality difference is very little_).
-
-- Added a default red colored Stderr output in case of a console command error.
- _You can now also silence individually custom commands errors using the `cobra.Command.SilenceErrors` field._
-
-- Fixed links formatting in the autogenerated html->text mail body.
-
-- Removed incorrectly imported empty `local('')` font-face declarations.
-
-
-## v0.19.4
-
-- Fixed TinyMCE source code viewer textarea styles ([#3715](https://github.com/pocketbase/pocketbase/issues/3715)).
-
-- Fixed `text` field min/max validators to properly count multi-byte characters ([#3735](https://github.com/pocketbase/pocketbase/issues/3735)).
-
-- Allowed hyphens in `username` ([#3697](https://github.com/pocketbase/pocketbase/issues/3697)).
- _More control over the system fields settings will be available in the future._
-
-- Updated the JSVM generated types to use directly the value type instead of `* | undefined` union in functions/methods return declarations.
-
-
-## v0.19.3
-
-- Added the release notes to the console output of `./pocketbase update` ([#3685](https://github.com/pocketbase/pocketbase/discussions/3685)).
-
-- Added missing documentation for the JSVM `$mails.*` bindings.
-
-- Relaxed the OAuth2 redirect url validation to allow any string value ([#3689](https://github.com/pocketbase/pocketbase/pull/3689); thanks @sergeypdev).
- _Note that the redirect url format is still bound to the accepted values by the specific OAuth2 provider._
-
-
-## v0.19.2
-
-- Updated the JSVM generated types ([#3627](https://github.com/pocketbase/pocketbase/issues/3627), [#3662](https://github.com/pocketbase/pocketbase/issues/3662)).
-
-
-## v0.19.1
-
-- Fixed `tokenizer.Scan()/ScanAll()` to ignore the separators from the default trim cutset.
- An option to return also the empty found tokens was also added via `Tokenizer.KeepEmptyTokens(true)`.
- _This should fix the parsing of whitespace characters around view query column names when no quotes are used ([#3616](https://github.com/pocketbase/pocketbase/discussions/3616#discussioncomment-7398564))._
-
-- Fixed the `:excerpt(max, withEllipsis?)` `fields` query param modifier to properly add space to the generated text fragment after block tags.
-
-
-## v0.19.0
-
-- Added Patreon OAuth2 provider ([#3323](https://github.com/pocketbase/pocketbase/pull/3323); thanks @ghostdevv).
-
-- Added mailcow OAuth2 provider ([#3364](https://github.com/pocketbase/pocketbase/pull/3364); thanks @thisni1s).
-
-- Added support for `:excerpt(max, withEllipsis?)` `fields` modifier that will return a short plain text version of any string value (html tags are stripped).
- This could be used to minimize the downloaded json data when listing records with large `editor` html values.
- ```js
- await pb.collection("example").getList(1, 20, {
- "fields": "*,description:excerpt(100)"
- })
- ```
-
-- Several Admin UI improvements:
- - Count the total records separately to speed up the query execution for large datasets ([#3344](https://github.com/pocketbase/pocketbase/issues/3344)).
- - Enclosed the listing scrolling area within the table so that the horizontal scrollbar and table header are always reachable ([#2505](https://github.com/pocketbase/pocketbase/issues/2505)).
- - Allowed opening the record preview/update form via direct URL ([#2682](https://github.com/pocketbase/pocketbase/discussions/2682)).
- - Reintroduced the local `date` field tooltip on hover.
- - Speed up the listing loading times for records with large `editor` field values by initially fetching only a partial of the records data (the complete record data is loaded on record preview/update).
- - Added "Media library" (collection images picker) support for the TinyMCE `editor` field.
- - Added support to "pin" collections in the sidebar.
- - Added support to manually resize the collections sidebar.
- - More clear "Nonempty" field label style.
- - Removed the legacy `.woff` and `.ttf` fonts and keep only `.woff2`.
-
-- Removed the explicit `Content-Type` charset from the realtime response due to compatibility issues with IIS ([#3461](https://github.com/pocketbase/pocketbase/issues/3461)).
- _The `Connection:keep-alive` realtime response header was also removed as it is not really used with HTTP2 anyway._
-
-- Added new JSVM bindings:
- - `new Cookie({ ... })` constructor for creating `*http.Cookie` equivalent value.
- - `new SubscriptionMessage({ ... })` constructor for creating a custom realtime subscription payload.
- - Soft-deprecated `$os.exec()` in favour of `$os.cmd()` to make it more clear that the call only prepares the command and doesn't execute it.
-
-- ⚠️ Bumped the min required Go version to 1.19.
-
-
-## v0.18.10
-
-- Added global `raw` template function to allow outputting raw/verbatim HTML content in the JSVM templates ([#3476](https://github.com/pocketbase/pocketbase/discussions/3476)).
- ```
- {{.description|raw}}
- ```
-
-- Trimmed view query semicolon and allowed single quotes for column aliases ([#3450](https://github.com/pocketbase/pocketbase/issues/3450#issuecomment-1748044641)).
- _Single quotes are usually [not a valid identifier quote characters](https://www.sqlite.org/lang_keywords.html), but for resilience and compatibility reasons SQLite allows them in some contexts where only an identifier is expected._
-
-- Bumped the GitHub action to use [min Go 1.21.2](https://github.com/golang/go/issues?q=milestone%3AGo1.21.2) (_the fixed issues are not critical as they are mostly related to the compiler/build tools_).
-
-
-## v0.18.9
-
-- Fixed empty thumbs directories not getting deleted on Windows after deleting a record img file ([#3382](https://github.com/pocketbase/pocketbase/issues/3382)).
-
-- Updated the generated JSVM typings to silent the TS warnings when trying to access a field/method in a Go->TS interface.
-
-
-## v0.18.8
-
-- Minor fix for the View collections API Preview and Admin UI listings incorrectly showing the `created` and `updated` fields as `N/A` when the view query doesn't have them.
-
-
-## v0.18.7
-
-- Fixed JS error in the Admin UI when listing records with invalid `relation` field value ([#3372](https://github.com/pocketbase/pocketbase/issues/3372)).
- _This could happen usually only during custom SQL import scripts or when directly modifying the record field value without data validations._
-
-- Updated Go deps and the generated JSVM types.
-
-
-## v0.18.6
-
-- Return the response headers and cookies in the `$http.send()` result ([#3310](https://github.com/pocketbase/pocketbase/discussions/3310)).
-
-- Added more descriptive internal error message for missing user/admin email on password reset requests.
-
-- Updated Go deps.
-
-
-## v0.18.5
-
-- Fixed minor Admin UI JS error in the auth collection options panel introduced with the change from v0.18.4.
-
-
-## v0.18.4
-
-- Added escape character (`\`) support in the Admin UI to allow using `select` field values with comma ([#2197](https://github.com/pocketbase/pocketbase/discussions/2197)).
-
-
-## v0.18.3
-
-- Exposed a global JSVM `readerToString(reader)` helper function to allow reading Go `io.Reader` values ([#3273](https://github.com/pocketbase/pocketbase/discussions/3273)).
-
-- Bumped the GitHub action to use [min Go 1.21.1](https://github.com/golang/go/issues?q=milestone%3AGo1.21.1+label%3ACherryPickApproved) for the prebuilt executable since it contains some minor `html/template` and `net/http` security fixes.
-
-
-## v0.18.2
-
-- Prevent breaking the record form in the Admin UI in case the browser's localStorage quota has been exceeded when uploading or storing large `editor` values ([#3265](https://github.com/pocketbase/pocketbase/issues/3265)).
-
-- Updated docs and missing JSVM typings.
-
-- Exposed additional crypto primitives under the `$security.*` JSVM namespace ([#3273](https://github.com/pocketbase/pocketbase/discussions/3273)):
- ```js
- // HMAC with SHA256
- $security.hs256("hello", "secret")
-
- // HMAC with SHA512
- $security.hs512("hello", "secret")
-
- // compare 2 strings with a constant time
- $security.equal(hash1, hash2)
- ```
-
-
-## v0.18.1
-
-- Excluded the local temp dir from the backups ([#3261](https://github.com/pocketbase/pocketbase/issues/3261)).
-
-
-## v0.18.0
-
-- Simplified the `serve` command to accept domain name(s) as argument to reduce any additional manual hosts setup that sometimes previously was needed when deploying on production ([#3190](https://github.com/pocketbase/pocketbase/discussions/3190)).
- ```sh
- ./pocketbase serve yourdomain.com
- ```
-
-- Added `fields` wildcard (`*`) support.
-
-- Added option to upload a backup file from the Admin UI ([#2599](https://github.com/pocketbase/pocketbase/issues/2599)).
-
-- Registered a custom Deflate compressor to speedup (_nearly 2-3x_) the backups generation for the sake of a small zip size increase.
- _Based on several local tests, `pb_data` of ~500MB (from which ~350MB+ are several hundred small files) results in a ~280MB zip generated for ~11s (previously it resulted in ~250MB zip but for ~35s)._
-
-- Added the application name as part of the autogenerated backup name for easier identification ([#3066](https://github.com/pocketbase/pocketbase/issues/3066)).
-
-- Added new `SmtpConfig.LocalName` option to specify a custom domain name (or IP address) for the initial EHLO/HELO exchange ([#3097](https://github.com/pocketbase/pocketbase/discussions/3097)).
- _This is usually required for verification purposes only by some SMTP providers, such as on-premise [Gmail SMTP-relay](https://support.google.com/a/answer/2956491)._
-
-- Added `NoDecimal` `number` field option.
-
-- `editor` field improvements:
- - Added new "Strip urls domain" option to allow controlling the default TinyMCE urls behavior (_default to `false` for new content_).
- - Normalized pasted text while still preserving links, lists, tables, etc. formatting ([#3257](https://github.com/pocketbase/pocketbase/issues/3257)).
-
-- Added option to auto generate admin and auth record passwords from the Admin UI.
-
-- Added JSON validation and syntax highlight for the `json` field in the Admin UI ([#3191](https://github.com/pocketbase/pocketbase/issues/3191)).
-
-- Added datetime filter macros:
- ```
- // all macros are UTC based
- @second - @now second number (0-59)
- @minute - @now minute number (0-59)
- @hour - @now hour number (0-23)
- @weekday - @now weekday number (0-6)
- @day - @now day number
- @month - @now month number
- @year - @now year number
- @todayStart - beginning of the current day as datetime string
- @todayEnd - end of the current day as datetime string
- @monthStart - beginning of the current month as datetime string
- @monthEnd - end of the current month as datetime string
- @yearStart - beginning of the current year as datetime string
- @yearEnd - end of the current year as datetime string
- ```
-
-- Added cron expression macros ([#3132](https://github.com/pocketbase/pocketbase/issues/3132)):
- ```
- @yearly - "0 0 1 1 *"
- @annually - "0 0 1 1 *"
- @monthly - "0 0 1 * *"
- @weekly - "0 0 * * 0"
- @daily - "0 0 * * *"
- @midnight - "0 0 * * *"
- @hourly - "0 * * * *"
- ```
-
-- ⚠️ Added offset argument `Dao.FindRecordsByFilter(collection, filter, sort, limit, offset, [params...])`.
- _If you don't need an offset, you can set it to `0`._
-
-- To minimize the footguns with `Dao.FindFirstRecordByFilter()` and `Dao.FindRecordsByFilter()`, the functions now supports an optional placeholder params argument that is safe to be populated with untrusted user input.
- The placeholders are in the same format as when binding regular SQL parameters.
- ```go
- // unsanitized and untrusted filter variables
- status := "..."
- author := "..."
-
- app.Dao().FindFirstRecordByFilter("articles", "status={:status} && author={:author}", dbx.Params{
- "status": status,
- "author": author,
- })
-
- app.Dao().FindRecordsByFilter("articles", "status={:status} && author={:author}", "-created", 10, 0, dbx.Params{
- "status": status,
- "author": author,
- })
- ```
-
-- Added JSVM `$mails.*` binds for the corresponding Go [mails package](https://pkg.go.dev/github.com/pocketbase/pocketbase/mails) functions.
-
-- Added JSVM helper crypto primitives under the `$security.*` namespace:
- ```js
- $security.md5(text)
- $security.sha256(text)
- $security.sha512(text)
- ```
-
-- ⚠️ Deprecated `RelationOptions.DisplayFields` in favor of the new `SchemaField.Presentable` option to avoid the duplication when a single collection is referenced more than once and/or by multiple other collections.
-
-- ⚠️ Fill the `LastVerificationSentAt` and `LastResetSentAt` fields only after a successfull email send ([#3121](https://github.com/pocketbase/pocketbase/issues/3121)).
-
-- ⚠️ Skip API `fields` json transformations for non 20x responses ([#3176](https://github.com/pocketbase/pocketbase/issues/3176)).
-
-- ⚠️ Changes to `tests.ApiScenario` struct:
-
- - The `ApiScenario.AfterTestFunc` now receive as 3rd argument `*http.Response` pointer instead of `*echo.Echo` as the latter is not really useful in this context.
- ```go
- // old
- AfterTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo)
-
- // new
- AfterTestFunc: func(t *testing.T, app *tests.TestApp, res *http.Response)
- ```
-
- - The `ApiScenario.TestAppFactory` now accept the test instance as argument and no longer expect an error as return result ([#3025](https://github.com/pocketbase/pocketbase/discussions/3025#discussioncomment-6592272)).
- ```go
- // old
- TestAppFactory: func() (*tests.TestApp, error)
-
- // new
- TestAppFactory: func(t *testing.T) *tests.TestApp
- ```
- _Returning a `nil` app instance from the factory results in test failure. You can enforce a custom test failure by calling `t.Fatal(err)` inside the factory._
-
-- Bumped the min required TLS version to 1.2 in order to improve the cert reputation score.
-
-- Reduced the default JSVM prewarmed pool size to 25 to reduce the initial memory consumptions (_you can manually adjust the pool size with `--hooksPool=50` if you need to, but the default should suffice for most cases_).
-
-- Update `gocloud.dev` dependency to v0.34 and explicitly set the new `NoTempDir` fileblob option to prevent the cross-device link error introduced with v0.33.
-
-- Other minor Admin UI and docs improvements.
-
-
-## v0.17.7
-
-- Fixed the autogenerated `down` migrations to properly revert the old collection rules in case a change was made in `up` ([#3192](https://github.com/pocketbase/pocketbase/pull/3192); thanks @impact-merlinmarek).
- _Existing `down` migrations can't be fixed but that should be ok as usually the `down` migrations are rarely used against prod environments since they can cause data loss and, while not ideal, the previous old behavior of always setting the rules to `null/nil` is safer than not updating the rules at all._
-
-- Updated some Go deps.
-
-
-## v0.17.6
-
-- Fixed JSVM `require()` file path error when using Windows-style path delimiters ([#3163](https://github.com/pocketbase/pocketbase/issues/3163#issuecomment-1685034438)).
-
-
-## v0.17.5
-
-- Added quotes around the wrapped view query columns introduced with v0.17.4.
-
-
-## v0.17.4
-
-- Fixed Views record retrieval when numeric id is used ([#3110](https://github.com/pocketbase/pocketbase/issues/3110)).
- _With this fix we also now properly recognize `CAST(... as TEXT)` and `CAST(... as BOOLEAN)` as `text` and `bool` fields._
-
-- Fixed `relation` "Cascade delete" tooltip message ([#3098](https://github.com/pocketbase/pocketbase/issues/3098)).
-
-- Fixed jsvm error message prefix on failed migrations ([#3103](https://github.com/pocketbase/pocketbase/pull/3103); thanks @nzhenev).
-
-- Disabled the initial Admin UI admins counter cache when there are no initial admins to allow detecting externally created accounts (eg. with the `admin` command) ([#3106](https://github.com/pocketbase/pocketbase/issues/3106)).
-
-- Downgraded `google/go-cloud` dependency to v0.32.0 until v0.34.0 is released to prevent the `os.TempDir` `cross-device link` errors as too many users complained about it.
-
-
-## v0.17.3
-
-- Fixed Docker `cross-device link` error when creating `pb_data` backups on a local mounted volume ([#3089](https://github.com/pocketbase/pocketbase/issues/3089)).
-
-- Fixed the error messages for relation to views ([#3090](https://github.com/pocketbase/pocketbase/issues/3090)).
-
-- Always reserve space for the scrollbar to reduce the layout shifts in the Admin UI records listing due to the deprecated `overflow: overlay`.
-
-- Enabled lazy loading for the Admin UI thumb images.
-
-
-## v0.17.2
-
-- Soft-deprecated `$http.send({ data: object, ... })` in favour of `$http.send({ body: rawString, ... })`
- to allow sending non-JSON body with the request ([#3058](https://github.com/pocketbase/pocketbase/discussions/3058)).
- The existing `data` prop will still work, but it is recommended to use `body` instead (_to send JSON you can use `JSON.stringify(...)` as body value_).
-
-- Added `core.RealtimeConnectEvent.IdleTimeout` field to allow specifying a different realtime idle timeout duration per client basis ([#3054](https://github.com/pocketbase/pocketbase/discussions/3054)).
-
-- Fixed `apis.RequestData` deprecation log note ([#3068](https://github.com/pocketbase/pocketbase/pull/3068); thanks @gungjodi).
-
-
-## v0.17.1
-
-- Use relative path when redirecting to the OAuth2 providers page in the Admin UI to support subpath deployments ([#3026](https://github.com/pocketbase/pocketbase/pull/3026); thanks @sonyarianto).
-
-- Manually trigger the `OnBeforeServe` hook for `tests.ApiScenario` ([#3025](https://github.com/pocketbase/pocketbase/discussions/3025)).
-
-- Trigger the JSVM `cronAdd()` handler only on app `serve` to prevent unexpected (and eventually duplicated) cron handler calls when custom console commands are used ([#3024](https://github.com/pocketbase/pocketbase/discussions/3024#discussioncomment-6592703)).
-
-- The `console.log()` messages are now written to the `stdout` instead of `stderr`.
-
-
-## v0.17.0
-
-- New more detailed guides for using PocketBase as framework (both Go and JS).
- _If you find any typos or issues with the docs please report them in https://github.com/pocketbase/site._
-
-- Added new experimental JavaScript app hooks binding via [goja](https://github.com/dop251/goja).
- They are available by default with the prebuilt executable if you create `*.pb.js` file(s) in the `pb_hooks` directory.
- Lower your expectations because the integration comes with some limitations. For more details please check the [Extend with JavaScript](https://pocketbase.io/docs/js-overview/) guide.
- Optionally, you can also enable the JS app hooks as part of a custom Go build for dynamic scripting but you need to register the `jsvm` plugin manually:
- ```go
- jsvm.MustRegister(app core.App, config jsvm.Config{})
- ```
-
-- Added Instagram OAuth2 provider ([#2534](https://github.com/pocketbase/pocketbase/pull/2534); thanks @pnmcosta).
-
-- Added VK OAuth2 provider ([#2533](https://github.com/pocketbase/pocketbase/pull/2533); thanks @imperatrona).
-
-- Added Yandex OAuth2 provider ([#2762](https://github.com/pocketbase/pocketbase/pull/2762); thanks @imperatrona).
-
-- Added new fields to `core.ServeEvent`:
- ```go
- type ServeEvent struct {
- App App
- Router *echo.Echo
- // new fields
- Server *http.Server // allows adjusting the HTTP server config (global timeouts, TLS options, etc.)
- CertManager *autocert.Manager // allows adjusting the autocert options (cache dir, host policy, etc.)
- }
- ```
-
-- Added `record.ExpandedOne(rel)` and `record.ExpandedAll(rel)` helpers to retrieve casted single or multiple expand relations from the already loaded "expand" Record data.
-
-- Added rule and filter record `Dao` helpers:
- ```go
- app.Dao().FindRecordsByFilter("posts", "title ~ 'lorem ipsum' && visible = true", "-created", 10)
- app.Dao().FindFirstRecordByFilter("posts", "slug='test' && active=true")
- app.Dao().CanAccessRecord(record, requestInfo, rule)
- ```
-
-- Added `Dao.WithoutHooks()` helper to create a new `Dao` from the current one but without the create/update/delete hooks.
-
-- Use a default fetch function that will return all relations in case the `fetchFunc` argument of `Dao.ExpandRecord(record, expands, fetchFunc)` and `Dao.ExpandRecords(records, expands, fetchFunc)` is `nil`.
-
-- For convenience it is now possible to call `Dao.RecordQuery(collectionModelOrIdentifier)` with just the collection id or name.
- In case an invalid collection id/name string is passed the query will be resolved with cancelled context error.
-
-- Refactored `apis.ApiError` validation errors serialization to allow `map[string]error` and `map[string]any` when generating the public safe formatted `ApiError.Data`.
-
-- Added support for wrapped API errors (_in case Go 1.20+ is used with multiple wrapped errors, the first `apis.ApiError` takes precedence_).
-
-- Added `?download=1` file query parameter to the file serving endpoint to force the browser to always download the file and not show its preview.
-
-- Added new utility `github.com/pocketbase/pocketbase/tools/template` subpackage to assist with rendering HTML templates using the standard Go `html/template` and `text/template` syntax.
-
-- Added `types.JsonMap.Get(k)` and `types.JsonMap.Set(k, v)` helpers for the cases where the type aliased direct map access is not allowed (eg. in [goja](https://pkg.go.dev/github.com/dop251/goja#hdr-Maps_with_methods)).
-
-- Soft-deprecated `security.NewToken()` in favor of `security.NewJWT()`.
-
-- `Hook.Add()` and `Hook.PreAdd` now returns a unique string identifier that could be used to remove the registered hook handler via `Hook.Remove(handlerId)`.
-
-- Changed the after* hooks to be called right before writing the user response, allowing users to return response errors from the after hooks.
- There is also no longer need for returning explicitly `hook.StopPropagtion` when writing custom response body in a hook because we will skip the finalizer response body write if a response was already "committed".
-
-- ⚠️ Renamed `*Options{}` to `Config{}` for consistency and replaced the unnecessary pointers with their value equivalent to keep the applied configuration defaults isolated within their function calls:
- ```go
- old: pocketbase.NewWithConfig(config *pocketbase.Config) *pocketbase.PocketBase
- new: pocketbase.NewWithConfig(config pocketbase.Config) *pocketbase.PocketBase
-
- old: core.NewBaseApp(config *core.BaseAppConfig) *core.BaseApp
- new: core.NewBaseApp(config core.BaseAppConfig) *core.BaseApp
-
- old: apis.Serve(app core.App, options *apis.ServeOptions) error
- new: apis.Serve(app core.App, config apis.ServeConfig) (*http.Server, error)
-
- old: jsvm.MustRegisterMigrations(app core.App, options *jsvm.MigrationsOptions)
- new: jsvm.MustRegister(app core.App, config jsvm.Config)
-
- old: ghupdate.MustRegister(app core.App, rootCmd *cobra.Command, options *ghupdate.Options)
- new: ghupdate.MustRegister(app core.App, rootCmd *cobra.Command, config ghupdate.Config)
-
- old: migratecmd.MustRegister(app core.App, rootCmd *cobra.Command, options *migratecmd.Options)
- new: migratecmd.MustRegister(app core.App, rootCmd *cobra.Command, config migratecmd.Config)
- ```
-
-- ⚠️ Changed the type of `subscriptions.Message.Data` from `string` to `[]byte` because `Data` usually is a json bytes slice anyway.
-
-- ⚠️ Renamed `models.RequestData` to `models.RequestInfo` and soft-deprecated `apis.RequestData(c)` in favor of `apis.RequestInfo(c)` to avoid the stuttering with the `Data` field.
- _The old `apis.RequestData()` method still works to minimize the breaking changes but it is recommended to replace it with `apis.RequestInfo(c)`._
-
-- ⚠️ Changes to the List/Search APIs
- - Added new query parameter `?skipTotal=1` to skip the `COUNT` query performed with the list/search actions ([#2965](https://github.com/pocketbase/pocketbase/discussions/2965)).
- If `?skipTotal=1` is set, the response fields `totalItems` and `totalPages` will have `-1` value (this is to avoid having different JSON responses and to differentiate from the zero default).
- With the latest JS SDK 0.16+ and Dart SDK v0.11+ versions `skipTotal=1` is set by default for the `getFirstListItem()` and `getFullList()` requests.
-
- - The count and regular select statements also now executes concurrently, meaning that we no longer perform normalization over the `page` parameter and in case the user
- request a page that doesn't exist (eg. `?page=99999999`) we'll return empty `items` array.
-
- - Reverted the default `COUNT` column to `id` as there are some common situations where it can negatively impact the query performance.
- Additionally, from this version we also set `PRAGMA temp_store = MEMORY` so that also helps with the temp B-TREE creation when `id` is used.
- _There are still scenarios where `COUNT` queries with `rowid` executes faster, but the majority of the time when nested relations lookups are used it seems to have the opposite effect (at least based on the benchmarks dataset)._
-
-- ⚠️ Disallowed relations to views **from non-view** collections ([#3000](https://github.com/pocketbase/pocketbase/issues/3000)).
- The change was necessary because I wasn't able to find an efficient way to track view changes and the previous behavior could have too many unexpected side-effects (eg. view with computed ids).
- There is a system migration that will convert the existing view `relation` fields to `json` (multiple) and `text` (single) fields.
- This could be a breaking change if you have `relation` to view and use `expand` or some of the `relation` view fields as part of a collection rule.
-
-- ⚠️ Added an extra `action` argument to the `Dao` hooks to allow skipping the default persist behavior.
- In preparation for the logs generalization, the `Dao.After*Func` methods now also allow returning an error.
-
-- Allowed `0` as `RelationOptions.MinSelect` value to avoid the ambiguity between 0 and non-filled input value ([#2817](https://github.com/pocketbase/pocketbase/discussions/2817)).
-
-- Fixed zero-default value not being used if the field is not explicitly set when manually creating records ([#2992](https://github.com/pocketbase/pocketbase/issues/2992)).
- Additionally, `record.Get(field)` will now always return normalized value (the same as in the json serialization) for consistency and to avoid ambiguities with what is stored in the related DB table.
- The schema fields columns `DEFAULT` definition was also updated for new collections to ensure that `NULL` values can't be accidentally inserted.
-
-- Fixed `migrate down` not returning the correct `lastAppliedMigrations()` when the stored migration applied time is in seconds.
-
-- Fixed realtime delete event to be called after the record was deleted from the DB (_including transactions and cascade delete operations_).
-
-- Other minor fixes and improvements (typos and grammar fixes, updated dependencies, removed unnecessary 404 error check in the Admin UI, etc.).
-
-
-## v0.16.10
-
-- Added multiple valued fields (`relation`, `select`, `file`) normalizations to ensure that the zero-default value of a newly created multiple field is applied for already existing data ([#2930](https://github.com/pocketbase/pocketbase/issues/2930)).
-
-
-## v0.16.9
-
-- Register the `eagerRequestInfoCache` middleware only for the internal `api` group routes to avoid conflicts with custom route handlers ([#2914](https://github.com/pocketbase/pocketbase/issues/2914)).
-
-
-## v0.16.8
-
-- Fixed unique validator detailed error message not being returned when camelCase field name is used ([#2868](https://github.com/pocketbase/pocketbase/issues/2868)).
-
-- Updated the index parser to allow no space between the table name and the columns list ([#2864](https://github.com/pocketbase/pocketbase/discussions/2864#discussioncomment-6373736)).
-
-- Updated go deps.
-
-
-## v0.16.7
-
-- Minor optimization for the list/search queries to use `rowid` with the `COUNT` statement when available.
- _This eliminates the temp B-TREE step when executing the query and for large datasets (eg. 150k) it could have 10x improvement (from ~580ms to ~60ms)._
-
-
-## v0.16.6
-
-- Fixed collection index column sort normalization in the Admin UI ([#2681](https://github.com/pocketbase/pocketbase/pull/2681); thanks @SimonLoir).
-
-- Removed unnecessary admins count in `apis.RequireAdminAuthOnlyIfAny()` middleware ([#2726](https://github.com/pocketbase/pocketbase/pull/2726); thanks @svekko).
-
-- Fixed `multipart/form-data` request bind not populating map array values ([#2763](https://github.com/pocketbase/pocketbase/discussions/2763#discussioncomment-6278902)).
-
-- Upgraded npm and Go dependencies.
-
-
-## v0.16.5
-
-- Fixed the Admin UI serialization of implicit relation display fields ([#2675](https://github.com/pocketbase/pocketbase/issues/2675)).
-
-- Reset the Admin UI sort in case the active sort collection field is renamed or deleted.
-
-
-## v0.16.4
-
-- Fixed the selfupdate command not working on Windows due to missing `.exe` in the extracted binary path ([#2589](https://github.com/pocketbase/pocketbase/discussions/2589)).
- _Note that the command on Windows will work from v0.16.4+ onwards, meaning that you still will have to update manually one more time to v0.16.4._
-
-- Added `int64`, `int32`, `uint`, `uint64` and `uint32` support when scanning `types.DateTime` ([#2602](https://github.com/pocketbase/pocketbase/discussions/2602))
-
-- Updated dependencies.
-
-
-## v0.16.3
-
-- Fixed schema fields sort not working on Safari/Gnome Web ([#2567](https://github.com/pocketbase/pocketbase/issues/2567)).
-
-- Fixed default `PRAGMA`s not being applied for new connections ([#2570](https://github.com/pocketbase/pocketbase/discussions/2570)).
-
-
-## v0.16.2
-
-- Fixed backups archive not excluding the local `backups` directory on Windows ([#2548](https://github.com/pocketbase/pocketbase/discussions/2548#discussioncomment-5979712)).
-
-- Changed file field to not use `dataTransfer.effectAllowed` when dropping files since it is not reliable and consistent across different OS and browsers ([#2541](https://github.com/pocketbase/pocketbase/issues/2541)).
-
-- Auto register the initial generated snapshot migration to prevent incorrectly reapplying the snapshot on Docker restart ([#2551](https://github.com/pocketbase/pocketbase/discussions/2551)).
-
-- Fixed missing view id field error message typo.
-
-
-## v0.16.1
-
-- Fixed backup restore not working in a container environment when `pb_data` is mounted as volume ([#2519](https://github.com/pocketbase/pocketbase/issues/2519)).
-
-- Fixed Dart SDK realtime API preview example ([#2523](https://github.com/pocketbase/pocketbase/pull/2523); thanks @xFrann).
-
-- Fixed typo in the backups create panel ([#2526](https://github.com/pocketbase/pocketbase/pull/2526); thanks @dschissler).
-
-- Removed unnecessary slice length check in `list.ExistInSlice` ([#2527](https://github.com/pocketbase/pocketbase/pull/2527); thanks @KunalSin9h).
-
-- Avoid mutating the cached request data on OAuth2 user create ([#2535](https://github.com/pocketbase/pocketbase/discussions/2535)).
-
-- Fixed Export Collections "Download as JSON" ([#2540](https://github.com/pocketbase/pocketbase/issues/2540)).
-
-- Fixed file field drag and drop not working in Firefox and Safari ([#2541](https://github.com/pocketbase/pocketbase/issues/2541)).
-
-
-## v0.16.0
-
-- Added automated backups (_+ cron rotation_) APIs and UI for the `pb_data` directory.
- The backups can be also initialized programmatically using `app.CreateBackup("backup.zip")`.
- There is also experimental restore method - `app.RestoreBackup("backup.zip")` (_currently works only on UNIX systems as it relies on execve_).
- The backups can be stored locally or in external S3 storage (_it has its own configuration, separate from the file uploads storage filesystem_).
-
-- Added option to limit the returned API fields using the `?fields` query parameter.
- The "fields picker" is applied for `SearchResult.Items` and every other JSON response. For example:
- ```js
- // original: {"id": "RECORD_ID", "name": "abc", "description": "...something very big...", "items": ["id1", "id2"], "expand": {"items": [{"id": "id1", "name": "test1"}, {"id": "id2", "name": "test2"}]}}
- // output: {"name": "abc", "expand": {"items": [{"name": "test1"}, {"name": "test2"}]}}
- const result = await pb.collection("example").getOne("RECORD_ID", {
- expand: "items",
- fields: "name,expand.items.name",
- })
- ```
-
-- Added new `./pocketbase update` command to selfupdate the prebuilt executable (with option to generate a backup of your `pb_data`).
-
-- Added new `./pocketbase admin` console command:
- ```sh
- // creates new admin account
- ./pocketbase admin create test@example.com 123456890
-
- // changes the password of an existing admin account
- ./pocketbase admin update test@example.com 0987654321
-
- // deletes single admin account (if exists)
- ./pocketbase admin delete test@example.com
- ```
-
-- Added `apis.Serve(app, options)` helper to allow starting the API server programmatically.
-
-- Updated the schema fields Admin UI for "tidier" fields visualization.
-
-- Updated the logs "real" user IP to check for `Fly-Client-IP` header and changed the `X-Forward-For` header to use the first non-empty leftmost-ish IP as it the closest to the "real IP".
-
-- Added new `tools/archive` helper subpackage for managing archives (_currently works only with zip_).
-
-- Added new `tools/cron` helper subpackage for scheduling task using cron-like syntax (_this eventually may get exported in the future in a separate repo_).
-
-- Added new `Filesystem.List(prefix)` helper to retrieve a flat list with all files under the provided prefix.
-
-- Added new `App.NewBackupsFilesystem()` helper to create a dedicated filesystem abstraction for managing app data backups.
-
-- Added new `App.OnTerminate()` hook (_executed right before app termination, eg. on `SIGTERM` signal_).
-
-- Added `accept` file field attribute with the field MIME types ([#2466](https://github.com/pocketbase/pocketbase/pull/2466); thanks @Nikhil1920).
-
-- Added support for multiple files sort in the Admin UI ([#2445](https://github.com/pocketbase/pocketbase/issues/2445)).
-
-- Added support for multiple relations sort in the Admin UI.
-
-- Added `meta.isNew` to the OAuth2 auth JSON response to indicate a newly OAuth2 created PocketBase user.
diff --git a/client/pb/LICENSE.md b/client/pb/LICENSE.md
deleted file mode 100644
index e3b8465..0000000
--- a/client/pb/LICENSE.md
+++ /dev/null
@@ -1,17 +0,0 @@
-The MIT License (MIT)
-Copyright (c) 2022 - present, Gani Georgiev
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software
-and associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or
-substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/client/pb/pb_hooks/main.pb.js b/client/pb/pb_hooks/main.pb.js
index 7f585e8..44bf76a 100644
--- a/client/pb/pb_hooks/main.pb.js
+++ b/client/pb/pb_hooks/main.pb.js
@@ -43,7 +43,7 @@ routerAdd(
})
)
- $app.dao().db().newQuery("SELECT DISTINCT DATE(created) as created FROM insights").all(result)
+ $app.dao().db().newQuery("SELECT DISTINCT DATE(created, 'localtime') as created FROM insights").all(result)
return c.json(
200,
diff --git a/client/web/.env.development b/client/web/.env.development
new file mode 100644
index 0000000..8a5ae01
--- /dev/null
+++ b/client/web/.env.development
@@ -0,0 +1,2 @@
+VITE_API_BASE=http://localhost:7777
+VITE_PB_BASE=http://localhost:8090
\ No newline at end of file
diff --git a/client/web/.env.production b/client/web/.env.production
new file mode 100644
index 0000000..8a5ae01
--- /dev/null
+++ b/client/web/.env.production
@@ -0,0 +1,2 @@
+VITE_API_BASE=http://localhost:7777
+VITE_PB_BASE=http://localhost:8090
\ No newline at end of file
diff --git a/client/web/.eslintrc.cjs b/client/web/.eslintrc.cjs
new file mode 100644
index 0000000..90cfe21
--- /dev/null
+++ b/client/web/.eslintrc.cjs
@@ -0,0 +1,13 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: ['eslint:recommended', 'plugin:react/recommended', 'plugin:react/jsx-runtime', 'plugin:react-hooks/recommended'],
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
+ parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
+ settings: { react: { version: '18.2' } },
+ plugins: ['react-refresh'],
+ rules: {
+ 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
+ 'react/prop-types': 'off',
+ },
+}
diff --git a/client/web/.gitignore b/client/web/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/client/web/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/client/web/README.md b/client/web/README.md
new file mode 100644
index 0000000..edeed30
--- /dev/null
+++ b/client/web/README.md
@@ -0,0 +1,6 @@
+web env:
+VITE_API_BASE=http://localhost:7777
+VITE_PB_BASE=http://localhost:8090
+
+pocketase env:
+AW_FILE_DIR=xxx
\ No newline at end of file
diff --git a/client/web/components.json b/client/web/components.json
new file mode 100644
index 0000000..92d235c
--- /dev/null
+++ b/client/web/components.json
@@ -0,0 +1,17 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "default",
+ "rsc": false,
+ "tsx": false,
+ "tailwind": {
+ "config": "tailwind.config.js",
+ "css": "src/index.css",
+ "baseColor": "slate",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils"
+ }
+}
\ No newline at end of file
diff --git a/client/web/index.html b/client/web/index.html
new file mode 100644
index 0000000..23b4f03
--- /dev/null
+++ b/client/web/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ 情报分析
+
+
+
+
+
+
diff --git a/client/web/package.json b/client/web/package.json
new file mode 100644
index 0000000..1bb8a36
--- /dev/null
+++ b/client/web/package.json
@@ -0,0 +1,56 @@
+{
+ "name": "asweb-react",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@hookform/resolvers": "^3.3.4",
+ "@radix-ui/react-accordion": "^1.1.2",
+ "@radix-ui/react-label": "^2.0.2",
+ "@radix-ui/react-slot": "^1.0.2",
+ "@radix-ui/react-toast": "^1.1.5",
+ "@rollup/rollup-linux-x64-gnu": "^4.9.6",
+ "@tanstack/react-query": "^5.17.9",
+ "@tanstack/react-query-devtools": "^5.17.9",
+ "axios": "^1.6.8",
+ "class-variance-authority": "^0.7.0",
+ "clsx": "^2.1.0",
+ "lucide-react": "^0.309.0",
+ "nanoid": "^5.0.4",
+ "pocketbase": "^0.21.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-hook-form": "^7.49.3",
+ "redaxios": "^0.5.1",
+ "tailwind-merge": "^2.2.0",
+ "tailwindcss-animate": "^1.0.7",
+ "wouter": "^3.1.0",
+ "zod": "^3.22.4",
+ "zustand": "^4.4.7"
+ },
+ "devDependencies": {
+ "@types/node": "^20.11.0",
+ "@types/react": "^18.2.43",
+ "@types/react-dom": "^18.2.17",
+ "@vitejs/plugin-react": "^4.2.1",
+ "autoprefixer": "^10.4.16",
+ "eslint": "^8.55.0",
+ "eslint-plugin-react": "^7.33.2",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.5",
+ "postcss": "^8.4.33",
+ "tailwindcss": "^3.4.1",
+ "vite": "^5.0.8"
+ },
+ "pnpm": {
+ "overrides": {
+ "rollup": "npm:@rollup/wasm-node"
+ }
+ }
+}
diff --git a/client/web/pnpm-lock.yaml b/client/web/pnpm-lock.yaml
new file mode 100644
index 0000000..e2be826
--- /dev/null
+++ b/client/web/pnpm-lock.yaml
@@ -0,0 +1,3374 @@
+lockfileVersion: '6.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+overrides:
+ rollup: npm:@rollup/wasm-node
+
+dependencies:
+ '@hookform/resolvers':
+ specifier: ^3.3.4
+ version: 3.3.4(react-hook-form@7.49.3)
+ '@radix-ui/react-accordion':
+ specifier: ^1.1.2
+ version: 1.1.2(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-label':
+ specifier: ^2.0.2
+ version: 2.0.2(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-slot':
+ specifier: ^1.0.2
+ version: 1.0.2(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-toast':
+ specifier: ^1.1.5
+ version: 1.1.5(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@rollup/rollup-linux-x64-gnu':
+ specifier: ^4.9.6
+ version: 4.9.6
+ '@tanstack/react-query':
+ specifier: ^5.17.9
+ version: 5.17.9(react@18.2.0)
+ '@tanstack/react-query-devtools':
+ specifier: ^5.17.9
+ version: 5.17.9(@tanstack/react-query@5.17.9)(react@18.2.0)
+ axios:
+ specifier: ^1.6.8
+ version: 1.6.8
+ class-variance-authority:
+ specifier: ^0.7.0
+ version: 0.7.0
+ clsx:
+ specifier: ^2.1.0
+ version: 2.1.0
+ lucide-react:
+ specifier: ^0.309.0
+ version: 0.309.0(react@18.2.0)
+ nanoid:
+ specifier: ^5.0.4
+ version: 5.0.4
+ pocketbase:
+ specifier: ^0.21.0
+ version: 0.21.0
+ react:
+ specifier: ^18.2.0
+ version: 18.2.0
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.2.0(react@18.2.0)
+ react-hook-form:
+ specifier: ^7.49.3
+ version: 7.49.3(react@18.2.0)
+ redaxios:
+ specifier: ^0.5.1
+ version: 0.5.1
+ tailwind-merge:
+ specifier: ^2.2.0
+ version: 2.2.0
+ tailwindcss-animate:
+ specifier: ^1.0.7
+ version: 1.0.7(tailwindcss@3.4.1)
+ wouter:
+ specifier: ^3.1.0
+ version: 3.1.0(react@18.2.0)
+ zod:
+ specifier: ^3.22.4
+ version: 3.22.4
+ zustand:
+ specifier: ^4.4.7
+ version: 4.4.7(@types/react@18.2.47)(react@18.2.0)
+
+devDependencies:
+ '@types/node':
+ specifier: ^20.11.0
+ version: 20.11.0
+ '@types/react':
+ specifier: ^18.2.43
+ version: 18.2.47
+ '@types/react-dom':
+ specifier: ^18.2.17
+ version: 18.2.18
+ '@vitejs/plugin-react':
+ specifier: ^4.2.1
+ version: 4.2.1(vite@5.0.11)
+ autoprefixer:
+ specifier: ^10.4.16
+ version: 10.4.16(postcss@8.4.33)
+ eslint:
+ specifier: ^8.55.0
+ version: 8.56.0
+ eslint-plugin-react:
+ specifier: ^7.33.2
+ version: 7.33.2(eslint@8.56.0)
+ eslint-plugin-react-hooks:
+ specifier: ^4.6.0
+ version: 4.6.0(eslint@8.56.0)
+ eslint-plugin-react-refresh:
+ specifier: ^0.4.5
+ version: 0.4.5(eslint@8.56.0)
+ postcss:
+ specifier: ^8.4.33
+ version: 8.4.33
+ tailwindcss:
+ specifier: ^3.4.1
+ version: 3.4.1
+ vite:
+ specifier: ^5.0.8
+ version: 5.0.11(@types/node@20.11.0)
+
+packages:
+
+ /@aashutoshrathi/word-wrap@1.2.6:
+ resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /@alloc/quick-lru@5.2.0:
+ resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
+ engines: {node: '>=10'}
+
+ /@ampproject/remapping@2.2.1:
+ resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/trace-mapping': 0.3.20
+ dev: true
+
+ /@babel/code-frame@7.23.5:
+ resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/highlight': 7.23.4
+ chalk: 2.4.2
+ dev: true
+
+ /@babel/compat-data@7.23.5:
+ resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/core@7.23.7:
+ resolution: {integrity: sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@ampproject/remapping': 2.2.1
+ '@babel/code-frame': 7.23.5
+ '@babel/generator': 7.23.6
+ '@babel/helper-compilation-targets': 7.23.6
+ '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.7)
+ '@babel/helpers': 7.23.8
+ '@babel/parser': 7.23.6
+ '@babel/template': 7.22.15
+ '@babel/traverse': 7.23.7
+ '@babel/types': 7.23.6
+ convert-source-map: 2.0.0
+ debug: 4.3.4
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/generator@7.23.6:
+ resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.6
+ '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/trace-mapping': 0.3.20
+ jsesc: 2.5.2
+ dev: true
+
+ /@babel/helper-compilation-targets@7.23.6:
+ resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/compat-data': 7.23.5
+ '@babel/helper-validator-option': 7.23.5
+ browserslist: 4.22.2
+ lru-cache: 5.1.1
+ semver: 6.3.1
+ dev: true
+
+ /@babel/helper-environment-visitor@7.22.20:
+ resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-function-name@7.23.0:
+ resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/template': 7.22.15
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/helper-hoist-variables@7.22.5:
+ resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/helper-module-imports@7.22.15:
+ resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.7):
+ resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.7
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-module-imports': 7.22.15
+ '@babel/helper-simple-access': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ '@babel/helper-validator-identifier': 7.22.20
+ dev: true
+
+ /@babel/helper-plugin-utils@7.22.5:
+ resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-simple-access@7.22.5:
+ resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/helper-split-export-declaration@7.22.6:
+ resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/helper-string-parser@7.23.4:
+ resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-validator-identifier@7.22.20:
+ resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-validator-option@7.23.5:
+ resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helpers@7.23.8:
+ resolution: {integrity: sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/template': 7.22.15
+ '@babel/traverse': 7.23.7
+ '@babel/types': 7.23.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/highlight@7.23.4:
+ resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-validator-identifier': 7.22.20
+ chalk: 2.4.2
+ js-tokens: 4.0.0
+ dev: true
+
+ /@babel/parser@7.23.6:
+ resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/plugin-transform-react-jsx-self@7.23.3(@babel/core@7.23.7):
+ resolution: {integrity: sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.7
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-react-jsx-source@7.23.3(@babel/core@7.23.7):
+ resolution: {integrity: sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.7
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/runtime@7.23.8:
+ resolution: {integrity: sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ regenerator-runtime: 0.14.1
+ dev: false
+
+ /@babel/template@7.22.15:
+ resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/code-frame': 7.23.5
+ '@babel/parser': 7.23.6
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/traverse@7.23.7:
+ resolution: {integrity: sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/code-frame': 7.23.5
+ '@babel/generator': 7.23.6
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-function-name': 7.23.0
+ '@babel/helper-hoist-variables': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ '@babel/parser': 7.23.6
+ '@babel/types': 7.23.6
+ debug: 4.3.4
+ globals: 11.12.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/types@7.23.6:
+ resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-string-parser': 7.23.4
+ '@babel/helper-validator-identifier': 7.22.20
+ to-fast-properties: 2.0.0
+ dev: true
+
+ /@esbuild/aix-ppc64@0.19.11:
+ resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm64@0.19.11:
+ resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm@0.19.11:
+ resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-x64@0.19.11:
+ resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-arm64@0.19.11:
+ resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-x64@0.19.11:
+ resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-arm64@0.19.11:
+ resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-x64@0.19.11:
+ resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm64@0.19.11:
+ resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm@0.19.11:
+ resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ia32@0.19.11:
+ resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-loong64@0.19.11:
+ resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-mips64el@0.19.11:
+ resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ppc64@0.19.11:
+ resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-riscv64@0.19.11:
+ resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-s390x@0.19.11:
+ resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-x64@0.19.11:
+ resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/netbsd-x64@0.19.11:
+ resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/openbsd-x64@0.19.11:
+ resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/sunos-x64@0.19.11:
+ resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-arm64@0.19.11:
+ resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-ia32@0.19.11:
+ resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-x64@0.19.11:
+ resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0):
+ resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+ dependencies:
+ eslint: 8.56.0
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
+ /@eslint-community/regexpp@4.10.0:
+ resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==}
+ engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+ dev: true
+
+ /@eslint/eslintrc@2.1.4:
+ resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ ajv: 6.12.6
+ debug: 4.3.4
+ espree: 9.6.1
+ globals: 13.24.0
+ ignore: 5.3.0
+ import-fresh: 3.3.0
+ js-yaml: 4.1.0
+ minimatch: 3.1.2
+ strip-json-comments: 3.1.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@eslint/js@8.56.0:
+ resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /@hookform/resolvers@3.3.4(react-hook-form@7.49.3):
+ resolution: {integrity: sha512-o5cgpGOuJYrd+iMKvkttOclgwRW86EsWJZZRC23prf0uU2i48Htq4PuT73AVb9ionFyZrwYEITuOFGF+BydEtQ==}
+ peerDependencies:
+ react-hook-form: ^7.0.0
+ dependencies:
+ react-hook-form: 7.49.3(react@18.2.0)
+ dev: false
+
+ /@humanwhocodes/config-array@0.11.14:
+ resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
+ engines: {node: '>=10.10.0'}
+ dependencies:
+ '@humanwhocodes/object-schema': 2.0.2
+ debug: 4.3.4
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@humanwhocodes/module-importer@1.0.1:
+ resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+ engines: {node: '>=12.22'}
+ dev: true
+
+ /@humanwhocodes/object-schema@2.0.2:
+ resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==}
+ dev: true
+
+ /@isaacs/cliui@8.0.2:
+ resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+ engines: {node: '>=12'}
+ dependencies:
+ string-width: 5.1.2
+ string-width-cjs: /string-width@4.2.3
+ strip-ansi: 7.1.0
+ strip-ansi-cjs: /strip-ansi@6.0.1
+ wrap-ansi: 8.1.0
+ wrap-ansi-cjs: /wrap-ansi@7.0.0
+
+ /@jridgewell/gen-mapping@0.3.3:
+ resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/set-array': 1.1.2
+ '@jridgewell/sourcemap-codec': 1.4.15
+ '@jridgewell/trace-mapping': 0.3.20
+
+ /@jridgewell/resolve-uri@3.1.1:
+ resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
+ engines: {node: '>=6.0.0'}
+
+ /@jridgewell/set-array@1.1.2:
+ resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
+ engines: {node: '>=6.0.0'}
+
+ /@jridgewell/sourcemap-codec@1.4.15:
+ resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
+
+ /@jridgewell/trace-mapping@0.3.20:
+ resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==}
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.1
+ '@jridgewell/sourcemap-codec': 1.4.15
+
+ /@nodelib/fs.scandir@2.1.5:
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ /@nodelib/fs.stat@2.0.5:
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ /@nodelib/fs.walk@1.2.8:
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.16.0
+
+ /@pkgjs/parseargs@0.11.0:
+ resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+ engines: {node: '>=14'}
+ requiresBuild: true
+ optional: true
+
+ /@radix-ui/primitive@1.0.1:
+ resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==}
+ dependencies:
+ '@babel/runtime': 7.23.8
+ dev: false
+
+ /@radix-ui/react-accordion@1.1.2(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-fDG7jcoNKVjSK6yfmuAs0EnPDro0WMXIhMtXdTBWqEioVW206ku+4Lw07e+13lUkFkpoEQ2PdeMIAGpdqEAmDg==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-collapsible': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-direction': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-id': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-id': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-slot': 1.0.2(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-context@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-direction@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-id@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-label@2.0.2(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-slot': 1.0.2(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-slot@1.0.2(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-toast@1.1.5(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-fRLn227WHIBRSzuRzGJ8W+5YALxofH23y0MlPLddaIpLpCDqdE0NZlS2NRQDRiptfxDeeCjgFIpexB1/zkxDlw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@rollup/rollup-linux-x64-gnu@4.9.6:
+ resolution: {integrity: sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==}
+ cpu: [x64]
+ os: [linux]
+ dev: false
+
+ /@rollup/wasm-node@4.13.2:
+ resolution: {integrity: sha512-4JXYomW63fBnXseG2mFkZwaNMDK0PkNamj9WD6H96FqEEl9ov3VjG3MK9UcOAj7Ap9o2weqSSCVng+QsxBeKfw==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+ dependencies:
+ '@types/estree': 1.0.5
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
+ /@tanstack/query-core@5.17.9:
+ resolution: {integrity: sha512-8xcvpWIPaRMDNLMvG9ugcUJMgFK316ZsqkPPbsI+TMZsb10N9jk0B6XgPk4/kgWC2ziHyWR7n7wUhxmD0pChQw==}
+ dev: false
+
+ /@tanstack/query-devtools@5.17.7:
+ resolution: {integrity: sha512-TfgvOqza5K7Sk6slxqkRIvXlEJoUoPSsGGwpuYSrpqgSwLSSvPPpZhq7hv7hcY5IvRoTNGoq6+MT01C/jILqoQ==}
+ dev: false
+
+ /@tanstack/react-query-devtools@5.17.9(@tanstack/react-query@5.17.9)(react@18.2.0):
+ resolution: {integrity: sha512-1viWP/jlO0LaeCdtTFqtF1k2RfM3KVpvwVffWv+PMNkS2u4s8YGUM17r3p82udbF9BY1mE7aHqQ3MM1errF5lQ==}
+ peerDependencies:
+ '@tanstack/react-query': ^5.17.9
+ react: ^18.0.0
+ dependencies:
+ '@tanstack/query-devtools': 5.17.7
+ '@tanstack/react-query': 5.17.9(react@18.2.0)
+ react: 18.2.0
+ dev: false
+
+ /@tanstack/react-query@5.17.9(react@18.2.0):
+ resolution: {integrity: sha512-M5E9gwUq1Stby/pdlYjBlL24euIVuGbWKIFCbtnQxSdXI4PgzjTSdXdV3QE6fc+itF+TUvX/JPTKIwq8yuBXcg==}
+ peerDependencies:
+ react: ^18.0.0
+ dependencies:
+ '@tanstack/query-core': 5.17.9
+ react: 18.2.0
+ dev: false
+
+ /@types/babel__core@7.20.5:
+ resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+ dependencies:
+ '@babel/parser': 7.23.6
+ '@babel/types': 7.23.6
+ '@types/babel__generator': 7.6.8
+ '@types/babel__template': 7.4.4
+ '@types/babel__traverse': 7.20.5
+ dev: true
+
+ /@types/babel__generator@7.6.8:
+ resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==}
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@types/babel__template@7.4.4:
+ resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+ dependencies:
+ '@babel/parser': 7.23.6
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@types/babel__traverse@7.20.5:
+ resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==}
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@types/estree@1.0.5:
+ resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
+ dev: true
+
+ /@types/node@20.11.0:
+ resolution: {integrity: sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==}
+ dependencies:
+ undici-types: 5.26.5
+ dev: true
+
+ /@types/prop-types@15.7.11:
+ resolution: {integrity: sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==}
+
+ /@types/react-dom@18.2.18:
+ resolution: {integrity: sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==}
+ dependencies:
+ '@types/react': 18.2.47
+
+ /@types/react@18.2.47:
+ resolution: {integrity: sha512-xquNkkOirwyCgoClNk85BjP+aqnIS+ckAJ8i37gAbDs14jfW/J23f2GItAf33oiUPQnqNMALiFeoM9Y5mbjpVQ==}
+ dependencies:
+ '@types/prop-types': 15.7.11
+ '@types/scheduler': 0.16.8
+ csstype: 3.1.3
+
+ /@types/scheduler@0.16.8:
+ resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==}
+
+ /@ungap/structured-clone@1.2.0:
+ resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
+ dev: true
+
+ /@vitejs/plugin-react@4.2.1(vite@5.0.11):
+ resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.2.0 || ^5.0.0
+ dependencies:
+ '@babel/core': 7.23.7
+ '@babel/plugin-transform-react-jsx-self': 7.23.3(@babel/core@7.23.7)
+ '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.7)
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.14.0
+ vite: 5.0.11(@types/node@20.11.0)
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /acorn-jsx@5.3.2(acorn@8.11.3):
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+ dependencies:
+ acorn: 8.11.3
+ dev: true
+
+ /acorn@8.11.3:
+ resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+ dev: true
+
+ /ajv@6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+ dev: true
+
+ /ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ /ansi-regex@6.0.1:
+ resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
+ engines: {node: '>=12'}
+
+ /ansi-styles@3.2.1:
+ resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+ engines: {node: '>=4'}
+ dependencies:
+ color-convert: 1.9.3
+ dev: true
+
+ /ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+ dependencies:
+ color-convert: 2.0.1
+
+ /ansi-styles@6.2.1:
+ resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
+ engines: {node: '>=12'}
+
+ /any-promise@1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+
+ /anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+
+ /arg@5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+
+ /argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ dev: true
+
+ /array-buffer-byte-length@1.0.0:
+ resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==}
+ dependencies:
+ call-bind: 1.0.5
+ is-array-buffer: 3.0.2
+ dev: true
+
+ /array-includes@3.1.7:
+ resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ is-string: 1.0.7
+ dev: true
+
+ /array.prototype.flat@1.3.2:
+ resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-shim-unscopables: 1.0.2
+ dev: true
+
+ /array.prototype.flatmap@1.3.2:
+ resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-shim-unscopables: 1.0.2
+ dev: true
+
+ /array.prototype.tosorted@1.1.2:
+ resolution: {integrity: sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-shim-unscopables: 1.0.2
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /arraybuffer.prototype.slice@1.0.2:
+ resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ array-buffer-byte-length: 1.0.0
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ is-array-buffer: 3.0.2
+ is-shared-array-buffer: 1.0.2
+ dev: true
+
+ /asynciterator.prototype@1.0.0:
+ resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+ dev: false
+
+ /autoprefixer@10.4.16(postcss@8.4.33):
+ resolution: {integrity: sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==}
+ engines: {node: ^10 || ^12 || >=14}
+ hasBin: true
+ peerDependencies:
+ postcss: ^8.1.0
+ dependencies:
+ browserslist: 4.22.2
+ caniuse-lite: 1.0.30001576
+ fraction.js: 4.3.7
+ normalize-range: 0.1.2
+ picocolors: 1.0.0
+ postcss: 8.4.33
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /available-typed-arrays@1.0.5:
+ resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /axios@1.6.8:
+ resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==}
+ dependencies:
+ follow-redirects: 1.15.6
+ form-data: 4.0.0
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+ dev: false
+
+ /balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+ /binary-extensions@2.2.0:
+ resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
+ engines: {node: '>=8'}
+
+ /brace-expansion@1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+ dev: true
+
+ /brace-expansion@2.0.1:
+ resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+ dependencies:
+ balanced-match: 1.0.2
+
+ /braces@3.0.2:
+ resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+ engines: {node: '>=8'}
+ dependencies:
+ fill-range: 7.0.1
+
+ /browserslist@4.22.2:
+ resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+ dependencies:
+ caniuse-lite: 1.0.30001576
+ electron-to-chromium: 1.4.628
+ node-releases: 2.0.14
+ update-browserslist-db: 1.0.13(browserslist@4.22.2)
+ dev: true
+
+ /call-bind@1.0.5:
+ resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==}
+ dependencies:
+ function-bind: 1.1.2
+ get-intrinsic: 1.2.2
+ set-function-length: 1.1.1
+ dev: true
+
+ /callsites@3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /camelcase-css@2.0.1:
+ resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
+ engines: {node: '>= 6'}
+
+ /caniuse-lite@1.0.30001576:
+ resolution: {integrity: sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==}
+ dev: true
+
+ /chalk@2.4.2:
+ resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+ engines: {node: '>=4'}
+ dependencies:
+ ansi-styles: 3.2.1
+ escape-string-regexp: 1.0.5
+ supports-color: 5.5.0
+ dev: true
+
+ /chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+ dev: true
+
+ /chokidar@3.5.3:
+ resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
+ engines: {node: '>= 8.10.0'}
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.2
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ /class-variance-authority@0.7.0:
+ resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==}
+ dependencies:
+ clsx: 2.0.0
+ dev: false
+
+ /clsx@2.0.0:
+ resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==}
+ engines: {node: '>=6'}
+ dev: false
+
+ /clsx@2.1.0:
+ resolution: {integrity: sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==}
+ engines: {node: '>=6'}
+ dev: false
+
+ /color-convert@1.9.3:
+ resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+ dependencies:
+ color-name: 1.1.3
+ dev: true
+
+ /color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+ dependencies:
+ color-name: 1.1.4
+
+ /color-name@1.1.3:
+ resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+ dev: true
+
+ /color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ /combined-stream@1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+ dependencies:
+ delayed-stream: 1.0.0
+ dev: false
+
+ /commander@4.1.1:
+ resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+ engines: {node: '>= 6'}
+
+ /concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+ dev: true
+
+ /convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ dev: true
+
+ /cross-spawn@7.0.3:
+ resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+ engines: {node: '>= 8'}
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ /cssesc@3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ /csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
+ /debug@4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+ dev: true
+
+ /deep-is@0.1.4:
+ resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+ dev: true
+
+ /define-data-property@1.1.1:
+ resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.2
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.1
+ dev: true
+
+ /define-properties@1.2.1:
+ resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.1
+ has-property-descriptors: 1.0.1
+ object-keys: 1.1.1
+ dev: true
+
+ /delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+ dev: false
+
+ /didyoumean@1.2.2:
+ resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
+
+ /dlv@1.1.3:
+ resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
+
+ /doctrine@2.1.0:
+ resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ esutils: 2.0.3
+ dev: true
+
+ /doctrine@3.0.0:
+ resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ esutils: 2.0.3
+ dev: true
+
+ /eastasianwidth@0.2.0:
+ resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+
+ /electron-to-chromium@1.4.628:
+ resolution: {integrity: sha512-2k7t5PHvLsufpP6Zwk0nof62yLOsCf032wZx7/q0mv8gwlXjhcxI3lz6f0jBr0GrnWKcm3burXzI3t5IrcdUxw==}
+ dev: true
+
+ /emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
+ /emoji-regex@9.2.2:
+ resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+
+ /es-abstract@1.22.3:
+ resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ array-buffer-byte-length: 1.0.0
+ arraybuffer.prototype.slice: 1.0.2
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.5
+ es-set-tostringtag: 2.0.2
+ es-to-primitive: 1.2.1
+ function.prototype.name: 1.1.6
+ get-intrinsic: 1.2.2
+ get-symbol-description: 1.0.0
+ globalthis: 1.0.3
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.1
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ hasown: 2.0.0
+ internal-slot: 1.0.6
+ is-array-buffer: 3.0.2
+ is-callable: 1.2.7
+ is-negative-zero: 2.0.2
+ is-regex: 1.1.4
+ is-shared-array-buffer: 1.0.2
+ is-string: 1.0.7
+ is-typed-array: 1.1.12
+ is-weakref: 1.0.2
+ object-inspect: 1.13.1
+ object-keys: 1.1.1
+ object.assign: 4.1.5
+ regexp.prototype.flags: 1.5.1
+ safe-array-concat: 1.0.1
+ safe-regex-test: 1.0.1
+ string.prototype.trim: 1.2.8
+ string.prototype.trimend: 1.0.7
+ string.prototype.trimstart: 1.0.7
+ typed-array-buffer: 1.0.0
+ typed-array-byte-length: 1.0.0
+ typed-array-byte-offset: 1.0.0
+ typed-array-length: 1.0.4
+ unbox-primitive: 1.0.2
+ which-typed-array: 1.1.13
+ dev: true
+
+ /es-iterator-helpers@1.0.15:
+ resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==}
+ dependencies:
+ asynciterator.prototype: 1.0.0
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-set-tostringtag: 2.0.2
+ function-bind: 1.1.2
+ get-intrinsic: 1.2.2
+ globalthis: 1.0.3
+ has-property-descriptors: 1.0.1
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ internal-slot: 1.0.6
+ iterator.prototype: 1.1.2
+ safe-array-concat: 1.0.1
+ dev: true
+
+ /es-set-tostringtag@2.0.2:
+ resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.2
+ has-tostringtag: 1.0.0
+ hasown: 2.0.0
+ dev: true
+
+ /es-shim-unscopables@1.0.2:
+ resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==}
+ dependencies:
+ hasown: 2.0.0
+ dev: true
+
+ /es-to-primitive@1.2.1:
+ resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ is-callable: 1.2.7
+ is-date-object: 1.0.5
+ is-symbol: 1.0.4
+ dev: true
+
+ /esbuild@0.19.11:
+ resolution: {integrity: sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.19.11
+ '@esbuild/android-arm': 0.19.11
+ '@esbuild/android-arm64': 0.19.11
+ '@esbuild/android-x64': 0.19.11
+ '@esbuild/darwin-arm64': 0.19.11
+ '@esbuild/darwin-x64': 0.19.11
+ '@esbuild/freebsd-arm64': 0.19.11
+ '@esbuild/freebsd-x64': 0.19.11
+ '@esbuild/linux-arm': 0.19.11
+ '@esbuild/linux-arm64': 0.19.11
+ '@esbuild/linux-ia32': 0.19.11
+ '@esbuild/linux-loong64': 0.19.11
+ '@esbuild/linux-mips64el': 0.19.11
+ '@esbuild/linux-ppc64': 0.19.11
+ '@esbuild/linux-riscv64': 0.19.11
+ '@esbuild/linux-s390x': 0.19.11
+ '@esbuild/linux-x64': 0.19.11
+ '@esbuild/netbsd-x64': 0.19.11
+ '@esbuild/openbsd-x64': 0.19.11
+ '@esbuild/sunos-x64': 0.19.11
+ '@esbuild/win32-arm64': 0.19.11
+ '@esbuild/win32-ia32': 0.19.11
+ '@esbuild/win32-x64': 0.19.11
+ dev: true
+
+ /escalade@3.1.1:
+ resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /escape-string-regexp@1.0.5:
+ resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+ engines: {node: '>=0.8.0'}
+ dev: true
+
+ /escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /eslint-plugin-react-hooks@4.6.0(eslint@8.56.0):
+ resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
+ dependencies:
+ eslint: 8.56.0
+ dev: true
+
+ /eslint-plugin-react-refresh@0.4.5(eslint@8.56.0):
+ resolution: {integrity: sha512-D53FYKJa+fDmZMtriODxvhwrO+IOqrxoEo21gMA0sjHdU6dPVH4OhyFip9ypl8HOF5RV5KdTo+rBQLvnY2cO8w==}
+ peerDependencies:
+ eslint: '>=7'
+ dependencies:
+ eslint: 8.56.0
+ dev: true
+
+ /eslint-plugin-react@7.33.2(eslint@8.56.0):
+ resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
+ dependencies:
+ array-includes: 3.1.7
+ array.prototype.flatmap: 1.3.2
+ array.prototype.tosorted: 1.1.2
+ doctrine: 2.1.0
+ es-iterator-helpers: 1.0.15
+ eslint: 8.56.0
+ estraverse: 5.3.0
+ jsx-ast-utils: 3.3.5
+ minimatch: 3.1.2
+ object.entries: 1.1.7
+ object.fromentries: 2.0.7
+ object.hasown: 1.1.3
+ object.values: 1.1.7
+ prop-types: 15.8.1
+ resolve: 2.0.0-next.5
+ semver: 6.3.1
+ string.prototype.matchall: 4.0.10
+ dev: true
+
+ /eslint-scope@7.2.2:
+ resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+ dev: true
+
+ /eslint-visitor-keys@3.4.3:
+ resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /eslint@8.56.0:
+ resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ hasBin: true
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0)
+ '@eslint-community/regexpp': 4.10.0
+ '@eslint/eslintrc': 2.1.4
+ '@eslint/js': 8.56.0
+ '@humanwhocodes/config-array': 0.11.14
+ '@humanwhocodes/module-importer': 1.0.1
+ '@nodelib/fs.walk': 1.2.8
+ '@ungap/structured-clone': 1.2.0
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.3
+ debug: 4.3.4
+ doctrine: 3.0.0
+ escape-string-regexp: 4.0.0
+ eslint-scope: 7.2.2
+ eslint-visitor-keys: 3.4.3
+ espree: 9.6.1
+ esquery: 1.5.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 6.0.1
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ globals: 13.24.0
+ graphemer: 1.4.0
+ ignore: 5.3.0
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ is-path-inside: 3.0.3
+ js-yaml: 4.1.0
+ json-stable-stringify-without-jsonify: 1.0.1
+ levn: 0.4.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.3
+ strip-ansi: 6.0.1
+ text-table: 0.2.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /espree@9.6.1:
+ resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ acorn: 8.11.3
+ acorn-jsx: 5.3.2(acorn@8.11.3)
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
+ /esquery@1.5.0:
+ resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
+ engines: {node: '>=0.10'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /esrecurse@4.3.0:
+ resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+ engines: {node: '>=4.0'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /estraverse@5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+ dev: true
+
+ /esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+ dev: true
+
+ /fast-glob@3.3.2:
+ resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
+ engines: {node: '>=8.6.0'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.5
+
+ /fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+ dev: true
+
+ /fast-levenshtein@2.0.6:
+ resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+ dev: true
+
+ /fastq@1.16.0:
+ resolution: {integrity: sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==}
+ dependencies:
+ reusify: 1.0.4
+
+ /file-entry-cache@6.0.1:
+ resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+ dependencies:
+ flat-cache: 3.2.0
+ dev: true
+
+ /fill-range@7.0.1:
+ resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ to-regex-range: 5.0.1
+
+ /find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+ dev: true
+
+ /flat-cache@3.2.0:
+ resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+ dependencies:
+ flatted: 3.2.9
+ keyv: 4.5.4
+ rimraf: 3.0.2
+ dev: true
+
+ /flatted@3.2.9:
+ resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==}
+ dev: true
+
+ /follow-redirects@1.15.6:
+ resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+ dev: false
+
+ /for-each@0.3.3:
+ resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
+ dependencies:
+ is-callable: 1.2.7
+ dev: true
+
+ /foreground-child@3.1.1:
+ resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
+ engines: {node: '>=14'}
+ dependencies:
+ cross-spawn: 7.0.3
+ signal-exit: 4.1.0
+
+ /form-data@4.0.0:
+ resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
+ engines: {node: '>= 6'}
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ mime-types: 2.1.35
+ dev: false
+
+ /fraction.js@4.3.7:
+ resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
+ dev: true
+
+ /fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+ dev: true
+
+ /fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ optional: true
+
+ /function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ /function.prototype.name@1.1.6:
+ resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ functions-have-names: 1.2.3
+ dev: true
+
+ /functions-have-names@1.2.3:
+ resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+ dev: true
+
+ /gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /get-intrinsic@1.2.2:
+ resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==}
+ dependencies:
+ function-bind: 1.1.2
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ hasown: 2.0.0
+ dev: true
+
+ /get-symbol-description@1.0.0:
+ resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+ dependencies:
+ is-glob: 4.0.3
+
+ /glob-parent@6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+ dependencies:
+ is-glob: 4.0.3
+
+ /glob@10.3.10:
+ resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+ dependencies:
+ foreground-child: 3.1.1
+ jackspeak: 2.3.6
+ minimatch: 9.0.3
+ minipass: 7.0.4
+ path-scurry: 1.10.1
+
+ /glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+ dev: true
+
+ /globals@11.12.0:
+ resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /globals@13.24.0:
+ resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ type-fest: 0.20.2
+ dev: true
+
+ /globalthis@1.0.3:
+ resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-properties: 1.2.1
+ dev: true
+
+ /gopd@1.0.1:
+ resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
+ dependencies:
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /graphemer@1.4.0:
+ resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+ dev: true
+
+ /has-bigints@1.0.2:
+ resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
+ dev: true
+
+ /has-flag@3.0.0:
+ resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /has-property-descriptors@1.0.1:
+ resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==}
+ dependencies:
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /has-proto@1.0.1:
+ resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-symbols@1.0.3:
+ resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-tostringtag@1.0.0:
+ resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /hasown@2.0.0:
+ resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ function-bind: 1.1.2
+
+ /ignore@5.3.0:
+ resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==}
+ engines: {node: '>= 4'}
+ dev: true
+
+ /import-fresh@3.3.0:
+ resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+ engines: {node: '>=6'}
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+ dev: true
+
+ /imurmurhash@0.1.4:
+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+ engines: {node: '>=0.8.19'}
+ dev: true
+
+ /inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+ dev: true
+
+ /inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ dev: true
+
+ /internal-slot@1.0.6:
+ resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.2
+ hasown: 2.0.0
+ side-channel: 1.0.4
+ dev: true
+
+ /is-array-buffer@3.0.2:
+ resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ is-typed-array: 1.1.12
+ dev: true
+
+ /is-async-function@2.0.0:
+ resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-bigint@1.0.4:
+ resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
+ dependencies:
+ has-bigints: 1.0.2
+ dev: true
+
+ /is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+ dependencies:
+ binary-extensions: 2.2.0
+
+ /is-boolean-object@1.1.2:
+ resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-callable@1.2.7:
+ resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-core-module@2.13.1:
+ resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
+ dependencies:
+ hasown: 2.0.0
+
+ /is-date-object@1.0.5:
+ resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ /is-finalizationregistry@1.0.2:
+ resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==}
+ dependencies:
+ call-bind: 1.0.5
+ dev: true
+
+ /is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+
+ /is-generator-function@1.0.10:
+ resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ is-extglob: 2.1.1
+
+ /is-map@2.0.2:
+ resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==}
+ dev: true
+
+ /is-negative-zero@2.0.2:
+ resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-number-object@1.0.7:
+ resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ /is-path-inside@3.0.3:
+ resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-regex@1.1.4:
+ resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-set@2.0.2:
+ resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==}
+ dev: true
+
+ /is-shared-array-buffer@1.0.2:
+ resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==}
+ dependencies:
+ call-bind: 1.0.5
+ dev: true
+
+ /is-string@1.0.7:
+ resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-symbol@1.0.4:
+ resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /is-typed-array@1.1.12:
+ resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ which-typed-array: 1.1.13
+ dev: true
+
+ /is-weakmap@2.0.1:
+ resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==}
+ dev: true
+
+ /is-weakref@1.0.2:
+ resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
+ dependencies:
+ call-bind: 1.0.5
+ dev: true
+
+ /is-weakset@2.0.2:
+ resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /isarray@2.0.5:
+ resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
+ dev: true
+
+ /isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ /iterator.prototype@1.1.2:
+ resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==}
+ dependencies:
+ define-properties: 1.2.1
+ get-intrinsic: 1.2.2
+ has-symbols: 1.0.3
+ reflect.getprototypeof: 1.0.4
+ set-function-name: 2.0.1
+ dev: true
+
+ /jackspeak@2.3.6:
+ resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
+ engines: {node: '>=14'}
+ dependencies:
+ '@isaacs/cliui': 8.0.2
+ optionalDependencies:
+ '@pkgjs/parseargs': 0.11.0
+
+ /jiti@1.21.0:
+ resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==}
+ hasBin: true
+
+ /js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ /js-yaml@4.1.0:
+ resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ dev: true
+
+ /jsesc@2.5.2:
+ resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
+ engines: {node: '>=4'}
+ hasBin: true
+ dev: true
+
+ /json-buffer@3.0.1:
+ resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+ dev: true
+
+ /json-schema-traverse@0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+ dev: true
+
+ /json-stable-stringify-without-jsonify@1.0.1:
+ resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+ dev: true
+
+ /json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+ dev: true
+
+ /jsx-ast-utils@3.3.5:
+ resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
+ engines: {node: '>=4.0'}
+ dependencies:
+ array-includes: 3.1.7
+ array.prototype.flat: 1.3.2
+ object.assign: 4.1.5
+ object.values: 1.1.7
+ dev: true
+
+ /keyv@4.5.4:
+ resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+ dependencies:
+ json-buffer: 3.0.1
+ dev: true
+
+ /levn@0.4.1:
+ resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ dev: true
+
+ /lilconfig@2.1.0:
+ resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
+ engines: {node: '>=10'}
+
+ /lilconfig@3.0.0:
+ resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==}
+ engines: {node: '>=14'}
+
+ /lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+
+ /locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-locate: 5.0.0
+ dev: true
+
+ /lodash.merge@4.6.2:
+ resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ dev: true
+
+ /loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+ dependencies:
+ js-tokens: 4.0.0
+
+ /lru-cache@10.1.0:
+ resolution: {integrity: sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==}
+ engines: {node: 14 || >=16.14}
+
+ /lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+ dependencies:
+ yallist: 3.1.1
+ dev: true
+
+ /lucide-react@0.309.0(react@18.2.0):
+ resolution: {integrity: sha512-zNVPczuwFrCfksZH3zbd1UDE6/WYhYAdbe2k7CImVyPAkXLgIwbs6eXQ4loigqDnUFjyFYCI5jZ1y10Kqal0dg==}
+ peerDependencies:
+ react: ^16.5.1 || ^17.0.0 || ^18.0.0
+ dependencies:
+ react: 18.2.0
+ dev: false
+
+ /merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ /micromatch@4.0.5:
+ resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ braces: 3.0.2
+ picomatch: 2.3.1
+
+ /mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+ dev: false
+
+ /mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+ dependencies:
+ mime-db: 1.52.0
+ dev: false
+
+ /minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ dependencies:
+ brace-expansion: 1.1.11
+ dev: true
+
+ /minimatch@9.0.3:
+ resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dependencies:
+ brace-expansion: 2.0.1
+
+ /minipass@7.0.4:
+ resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ /mitt@3.0.1:
+ resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
+ dev: false
+
+ /ms@2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+ dev: true
+
+ /mz@2.7.0:
+ resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+ dependencies:
+ any-promise: 1.3.0
+ object-assign: 4.1.1
+ thenify-all: 1.6.0
+
+ /nanoid@3.3.7:
+ resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ /nanoid@5.0.4:
+ resolution: {integrity: sha512-vAjmBf13gsmhXSgBrtIclinISzFFy22WwCYoyilZlsrRXNIHSwgFQ1bEdjRwMT3aoadeIF6HMuDRlOxzfXV8ig==}
+ engines: {node: ^18 || >=20}
+ hasBin: true
+ dev: false
+
+ /natural-compare@1.4.0:
+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ dev: true
+
+ /node-releases@2.0.14:
+ resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
+ dev: true
+
+ /normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+
+ /normalize-range@0.1.2:
+ resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ /object-hash@3.0.0:
+ resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
+ engines: {node: '>= 6'}
+
+ /object-inspect@1.13.1:
+ resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
+ dev: true
+
+ /object-keys@1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /object.assign@4.1.5:
+ resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ has-symbols: 1.0.3
+ object-keys: 1.1.1
+ dev: true
+
+ /object.entries@1.1.7:
+ resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /object.fromentries@2.0.7:
+ resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /object.hasown@1.1.3:
+ resolution: {integrity: sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==}
+ dependencies:
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /object.values@1.1.7:
+ resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+ dependencies:
+ wrappy: 1.0.2
+ dev: true
+
+ /optionator@0.9.3:
+ resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ '@aashutoshrathi/word-wrap': 1.2.6
+ deep-is: 0.1.4
+ fast-levenshtein: 2.0.6
+ levn: 0.4.1
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ dev: true
+
+ /p-limit@3.1.0:
+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ yocto-queue: 0.1.0
+ dev: true
+
+ /p-locate@5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-limit: 3.1.0
+ dev: true
+
+ /parent-module@1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+ dependencies:
+ callsites: 3.1.0
+ dev: true
+
+ /path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ /path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+ /path-scurry@1.10.1:
+ resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dependencies:
+ lru-cache: 10.1.0
+ minipass: 7.0.4
+
+ /picocolors@1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+
+ /picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+
+ /pify@2.3.0:
+ resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
+ engines: {node: '>=0.10.0'}
+
+ /pirates@4.0.6:
+ resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
+ engines: {node: '>= 6'}
+
+ /pocketbase@0.21.0:
+ resolution: {integrity: sha512-WGA5qxW9jzwOTx0i3FNhkKBlT2F5EvC8qZDYv14SB3BeOZVAqs6wMTj7vAXD52V0Fg8zF4XPHJCAJK04fw1rqg==}
+ dev: false
+
+ /postcss-import@15.1.0(postcss@8.4.33):
+ resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ postcss: ^8.0.0
+ dependencies:
+ postcss: 8.4.33
+ postcss-value-parser: 4.2.0
+ read-cache: 1.0.0
+ resolve: 1.22.8
+
+ /postcss-js@4.0.1(postcss@8.4.33):
+ resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
+ engines: {node: ^12 || ^14 || >= 16}
+ peerDependencies:
+ postcss: ^8.4.21
+ dependencies:
+ camelcase-css: 2.0.1
+ postcss: 8.4.33
+
+ /postcss-load-config@4.0.2(postcss@8.4.33):
+ resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
+ engines: {node: '>= 14'}
+ peerDependencies:
+ postcss: '>=8.0.9'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ postcss:
+ optional: true
+ ts-node:
+ optional: true
+ dependencies:
+ lilconfig: 3.0.0
+ postcss: 8.4.33
+ yaml: 2.3.4
+
+ /postcss-nested@6.0.1(postcss@8.4.33):
+ resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==}
+ engines: {node: '>=12.0'}
+ peerDependencies:
+ postcss: ^8.2.14
+ dependencies:
+ postcss: 8.4.33
+ postcss-selector-parser: 6.0.15
+
+ /postcss-selector-parser@6.0.15:
+ resolution: {integrity: sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==}
+ engines: {node: '>=4'}
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+
+ /postcss-value-parser@4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+
+ /postcss@8.4.33:
+ resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+
+ /prelude-ls@1.2.1:
+ resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+ engines: {node: '>= 0.8.0'}
+ dev: true
+
+ /prop-types@15.8.1:
+ resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ dependencies:
+ loose-envify: 1.4.0
+ object-assign: 4.1.1
+ react-is: 16.13.1
+ dev: true
+
+ /proxy-from-env@1.1.0:
+ resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+ dev: false
+
+ /punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+ /react-dom@18.2.0(react@18.2.0):
+ resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
+ peerDependencies:
+ react: ^18.2.0
+ dependencies:
+ loose-envify: 1.4.0
+ react: 18.2.0
+ scheduler: 0.23.0
+ dev: false
+
+ /react-hook-form@7.49.3(react@18.2.0):
+ resolution: {integrity: sha512-foD6r3juidAT1cOZzpmD/gOKt7fRsDhXXZ0y28+Al1CHgX+AY1qIN9VSIIItXRq1dN68QrRwl1ORFlwjBaAqeQ==}
+ engines: {node: '>=18', pnpm: '8'}
+ peerDependencies:
+ react: ^16.8.0 || ^17 || ^18
+ dependencies:
+ react: 18.2.0
+ dev: false
+
+ /react-is@16.13.1:
+ resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
+ dev: true
+
+ /react-refresh@0.14.0:
+ resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /react@18.2.0:
+ resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: false
+
+ /read-cache@1.0.0:
+ resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
+ dependencies:
+ pify: 2.3.0
+
+ /readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+ dependencies:
+ picomatch: 2.3.1
+
+ /redaxios@0.5.1:
+ resolution: {integrity: sha512-FSD2AmfdbkYwl7KDExYQlVvIrFz6Yd83pGfaGjBzM9F6rpq8g652Q4Yq5QD4c+nf4g2AgeElv1y+8ajUPiOYMg==}
+ dev: false
+
+ /reflect.getprototypeof@1.0.4:
+ resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ globalthis: 1.0.3
+ which-builtin-type: 1.1.3
+ dev: true
+
+ /regenerator-runtime@0.14.1:
+ resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
+ dev: false
+
+ /regexp.prototype.flags@1.5.1:
+ resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ set-function-name: 2.0.1
+ dev: true
+
+ /regexparam@3.0.0:
+ resolution: {integrity: sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==}
+ engines: {node: '>=8'}
+ dev: false
+
+ /resolve-from@4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /resolve@1.22.8:
+ resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.13.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
+ /resolve@2.0.0-next.5:
+ resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.13.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
+ /reusify@1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ /rimraf@3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ hasBin: true
+ dependencies:
+ glob: 7.2.3
+ dev: true
+
+ /run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ dependencies:
+ queue-microtask: 1.2.3
+
+ /safe-array-concat@1.0.1:
+ resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==}
+ engines: {node: '>=0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ has-symbols: 1.0.3
+ isarray: 2.0.5
+ dev: true
+
+ /safe-regex-test@1.0.1:
+ resolution: {integrity: sha512-Y5NejJTTliTyY4H7sipGqY+RX5P87i3F7c4Rcepy72nq+mNLhIsD0W4c7kEmduMDQCSqtPsXPlSTsFhh2LQv+g==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ is-regex: 1.1.4
+ dev: true
+
+ /scheduler@0.23.0:
+ resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: false
+
+ /semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+ dev: true
+
+ /set-function-length@1.1.1:
+ resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.1
+ get-intrinsic: 1.2.2
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.1
+ dev: true
+
+ /set-function-name@2.0.1:
+ resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.1
+ functions-have-names: 1.2.3
+ has-property-descriptors: 1.0.1
+ dev: true
+
+ /shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+ dependencies:
+ shebang-regex: 3.0.0
+
+ /shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ /side-channel@1.0.4:
+ resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ object-inspect: 1.13.1
+ dev: true
+
+ /signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+
+ /source-map-js@1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+
+ /string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+
+ /string-width@5.1.2:
+ resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+ engines: {node: '>=12'}
+ dependencies:
+ eastasianwidth: 0.2.0
+ emoji-regex: 9.2.2
+ strip-ansi: 7.1.0
+
+ /string.prototype.matchall@4.0.10:
+ resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ has-symbols: 1.0.3
+ internal-slot: 1.0.6
+ regexp.prototype.flags: 1.5.1
+ set-function-name: 2.0.1
+ side-channel: 1.0.4
+ dev: true
+
+ /string.prototype.trim@1.2.8:
+ resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /string.prototype.trimend@1.0.7:
+ resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /string.prototype.trimstart@1.0.7:
+ resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-regex: 5.0.1
+
+ /strip-ansi@7.1.0:
+ resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-regex: 6.0.1
+
+ /strip-json-comments@3.1.1:
+ resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /sucrase@3.35.0:
+ resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.3
+ commander: 4.1.1
+ glob: 10.3.10
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.6
+ ts-interface-checker: 0.1.13
+
+ /supports-color@5.5.0:
+ resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+ engines: {node: '>=4'}
+ dependencies:
+ has-flag: 3.0.0
+ dev: true
+
+ /supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+
+ /tailwind-merge@2.2.0:
+ resolution: {integrity: sha512-SqqhhaL0T06SW59+JVNfAqKdqLs0497esifRrZ7jOaefP3o64fdFNDMrAQWZFMxTLJPiHVjRLUywT8uFz1xNWQ==}
+ dependencies:
+ '@babel/runtime': 7.23.8
+ dev: false
+
+ /tailwindcss-animate@1.0.7(tailwindcss@3.4.1):
+ resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==}
+ peerDependencies:
+ tailwindcss: '>=3.0.0 || insiders'
+ dependencies:
+ tailwindcss: 3.4.1
+ dev: false
+
+ /tailwindcss@3.4.1:
+ resolution: {integrity: sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+ dependencies:
+ '@alloc/quick-lru': 5.2.0
+ arg: 5.0.2
+ chokidar: 3.5.3
+ didyoumean: 1.2.2
+ dlv: 1.1.3
+ fast-glob: 3.3.2
+ glob-parent: 6.0.2
+ is-glob: 4.0.3
+ jiti: 1.21.0
+ lilconfig: 2.1.0
+ micromatch: 4.0.5
+ normalize-path: 3.0.0
+ object-hash: 3.0.0
+ picocolors: 1.0.0
+ postcss: 8.4.33
+ postcss-import: 15.1.0(postcss@8.4.33)
+ postcss-js: 4.0.1(postcss@8.4.33)
+ postcss-load-config: 4.0.2(postcss@8.4.33)
+ postcss-nested: 6.0.1(postcss@8.4.33)
+ postcss-selector-parser: 6.0.15
+ resolve: 1.22.8
+ sucrase: 3.35.0
+ transitivePeerDependencies:
+ - ts-node
+
+ /text-table@0.2.0:
+ resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+ dev: true
+
+ /thenify-all@1.6.0:
+ resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+ engines: {node: '>=0.8'}
+ dependencies:
+ thenify: 3.3.1
+
+ /thenify@3.3.1:
+ resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+ dependencies:
+ any-promise: 1.3.0
+
+ /to-fast-properties@2.0.0:
+ resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+ dependencies:
+ is-number: 7.0.0
+
+ /ts-interface-checker@0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+
+ /type-check@0.4.0:
+ resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ dev: true
+
+ /type-fest@0.20.2:
+ resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /typed-array-buffer@1.0.0:
+ resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-byte-length@1.0.0:
+ resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ has-proto: 1.0.1
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-byte-offset@1.0.0:
+ resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ has-proto: 1.0.1
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-length@1.0.4:
+ resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==}
+ dependencies:
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ is-typed-array: 1.1.12
+ dev: true
+
+ /unbox-primitive@1.0.2:
+ resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
+ dependencies:
+ call-bind: 1.0.5
+ has-bigints: 1.0.2
+ has-symbols: 1.0.3
+ which-boxed-primitive: 1.0.2
+ dev: true
+
+ /undici-types@5.26.5:
+ resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+ dev: true
+
+ /update-browserslist-db@1.0.13(browserslist@4.22.2):
+ resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+ dependencies:
+ browserslist: 4.22.2
+ escalade: 3.1.1
+ picocolors: 1.0.0
+ dev: true
+
+ /uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ dependencies:
+ punycode: 2.3.1
+ dev: true
+
+ /use-sync-external-store@1.2.0(react@18.2.0):
+ resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ dependencies:
+ react: 18.2.0
+ dev: false
+
+ /util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+ /vite@5.0.11(@types/node@20.11.0):
+ resolution: {integrity: sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || >=20.0.0
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ dependencies:
+ '@types/node': 20.11.0
+ esbuild: 0.19.11
+ postcss: 8.4.33
+ rollup: /@rollup/wasm-node@4.13.2
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
+ /which-boxed-primitive@1.0.2:
+ resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
+ dependencies:
+ is-bigint: 1.0.4
+ is-boolean-object: 1.1.2
+ is-number-object: 1.0.7
+ is-string: 1.0.7
+ is-symbol: 1.0.4
+ dev: true
+
+ /which-builtin-type@1.1.3:
+ resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ function.prototype.name: 1.1.6
+ has-tostringtag: 1.0.0
+ is-async-function: 2.0.0
+ is-date-object: 1.0.5
+ is-finalizationregistry: 1.0.2
+ is-generator-function: 1.0.10
+ is-regex: 1.1.4
+ is-weakref: 1.0.2
+ isarray: 2.0.5
+ which-boxed-primitive: 1.0.2
+ which-collection: 1.0.1
+ which-typed-array: 1.1.13
+ dev: true
+
+ /which-collection@1.0.1:
+ resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==}
+ dependencies:
+ is-map: 2.0.2
+ is-set: 2.0.2
+ is-weakmap: 2.0.1
+ is-weakset: 2.0.2
+ dev: true
+
+ /which-typed-array@1.1.13:
+ resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ gopd: 1.0.1
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+ dependencies:
+ isexe: 2.0.0
+
+ /wouter@3.1.0(react@18.2.0):
+ resolution: {integrity: sha512-hou3w+12BMTBckdWdyJp/z7+kKcbdLDWfz6omSyrO6bbx4irNuQQyLDQkfSGXXJCxmglea3c8On9XFUkBSU8+Q==}
+ peerDependencies:
+ react: '>=16.8.0'
+ dependencies:
+ mitt: 3.0.1
+ react: 18.2.0
+ regexparam: 3.0.0
+ use-sync-external-store: 1.2.0(react@18.2.0)
+ dev: false
+
+ /wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ /wrap-ansi@8.1.0:
+ resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-styles: 6.2.1
+ string-width: 5.1.2
+ strip-ansi: 7.1.0
+
+ /wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+ dev: true
+
+ /yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+ dev: true
+
+ /yaml@2.3.4:
+ resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==}
+ engines: {node: '>= 14'}
+
+ /yocto-queue@0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /zod@3.22.4:
+ resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}
+ dev: false
+
+ /zustand@4.4.7(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==}
+ engines: {node: '>=12.7.0'}
+ peerDependencies:
+ '@types/react': '>=16.8'
+ immer: '>=9.0'
+ react: '>=16.8'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ immer:
+ optional: true
+ react:
+ optional: true
+ dependencies:
+ '@types/react': 18.2.47
+ react: 18.2.0
+ use-sync-external-store: 1.2.0(react@18.2.0)
+ dev: false
diff --git a/client/web/postcss.config.js b/client/web/postcss.config.js
new file mode 100644
index 0000000..2e7af2b
--- /dev/null
+++ b/client/web/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/client/web/public/vite.svg b/client/web/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/client/web/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/web/src/App.css b/client/web/src/App.css
new file mode 100644
index 0000000..917a0a9
--- /dev/null
+++ b/client/web/src/App.css
@@ -0,0 +1,13 @@
+#root {
+ max-width: 1280px;
+ min-height: 100%;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+html,
+body {
+ width: 100%;
+ height: 100%;
+}
diff --git a/client/web/src/App.jsx b/client/web/src/App.jsx
new file mode 100644
index 0000000..ca23aef
--- /dev/null
+++ b/client/web/src/App.jsx
@@ -0,0 +1,54 @@
+import { QueryClient, QueryClientProvider, QueryCache, useQueryClient } from "@tanstack/react-query"
+import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
+
+import "./App.css"
+
+import { Toaster } from "@/components/ui/toaster"
+import { useToast } from "@/components/ui/use-toast"
+import { Button } from "@/components/ui/button"
+import LoginScreen from "@/components/screen/login"
+// import Steps from "@/components/screen/steps"
+import InsightsScreen from "@/components/screen/insights"
+import ArticlesScreen from "@/components/screen/articles"
+import ReportScreen from "@/components/screen/report"
+
+import { isAuth } from "@/store"
+
+const queryClient = new QueryClient()
+
+import { Route, Switch, useLocation } from "wouter"
+
+function App() {
+ const [, setLocation] = useLocation()
+ if (!isAuth()) {
+ setLocation("/login")
+ }
+ // const { toast } = useToast()
+
+ return (
+
+
+
+
+
+
+
+ 404
+
+ {/* {
+ toast({
+ title: "Scheduled: Catch up",
+ description: "Friday, February 10, 2023 at 5:57 PM",
+ })
+ }}
+ >
+ Show Toast
+ */}
+
+
+
+ )
+}
+
+export default App
diff --git a/client/web/src/assets/react.svg b/client/web/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/client/web/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/web/src/components/article-list.jsx b/client/web/src/components/article-list.jsx
new file mode 100644
index 0000000..6bf6867
--- /dev/null
+++ b/client/web/src/components/article-list.jsx
@@ -0,0 +1,33 @@
+import { Button } from "@/components/ui/button"
+import { Delete } from "lucide-react"
+
+// data expecting object {"0":{}, "1":{}}
+export function ArticleList({ data, showActions, onDelete }) {
+ return (
+
+
+ {data &&
+ data.map((article, i) => (
+
+
+
+ {showActions && (
+ onDelete(article.id)}>
+
+
+ )}
+
+
+ ))}
+
+ {data &&
共{Object.keys(data).length}篇文章
}
+
+ )
+}
diff --git a/client/web/src/components/layout/step.jsx b/client/web/src/components/layout/step.jsx
new file mode 100644
index 0000000..b329913
--- /dev/null
+++ b/client/web/src/components/layout/step.jsx
@@ -0,0 +1,21 @@
+import { Button } from "@/components/ui/button"
+
+export default function StepLayout({ title, description, children, navigate }) {
+ return (
+ <>
+
+
+
+
{title}
+ {description &&
{description}
}
+
+ {/*
navigate("/start")}>
+ 新建任务
+ */}
+
+
+ {children}
+
+ >
+ )
+}
diff --git a/client/web/src/components/screen/articles.jsx b/client/web/src/components/screen/articles.jsx
new file mode 100644
index 0000000..2c3045f
--- /dev/null
+++ b/client/web/src/components/screen/articles.jsx
@@ -0,0 +1,74 @@
+import { useEffect } from "react"
+import { Button } from "@/components/ui/button"
+import { ArticleList } from "../article-list"
+import { useMutation, useQueryClient } from "@tanstack/react-query"
+import { Languages } from "lucide-react"
+import { ButtonLoading } from "@/components/ui/button-loading"
+import { useDatePager, useArticleDates, useArticles, translations } from "@/store"
+
+import { useLocation } from "wouter"
+
+function ArticlesScreen({}) {
+ const [, navigate] = useLocation()
+
+ const queryDates = useArticleDates()
+ const { index, last, next, hasLast, hasNext } = useDatePager(queryDates.data)
+ const currentDate = queryDates.data && index >= 0 ? queryDates.data[index] : ""
+ const query = useArticles(currentDate)
+ const queryClient = useQueryClient()
+
+ const mut = useMutation({
+ mutationFn: (data) => {
+ return translations(data)
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ["articles", currentDate] })
+ },
+ })
+
+ function trans() {
+ mut.mutate({ article_ids: query.data.map((d) => d.id) })
+ }
+
+ return (
+ <>
+ 文章
+ {query.isError && {query.error.message}
}
+
+ navigate("/insights")}>查看分析结果
+ {mut.isPending && }
+ {!mut.isPending && query.data && query.data.length > 0 && query.data.filter((a) => !a.translation_result).length > 0 && (
+
+
+ 一键翻译
+
+ )}
+
+ {currentDate && (
+
+
+ <
+
+
{currentDate}
+
+ >
+
+
+ )}
+ {/* {completed && !Object.values(query.data.articles)[0]["zh-cn"] && (
+
+
+ 一键翻译
+
+ )} */}
+
+ {query.data && }
+
+
+ navigate("/insights")}>查看分析结果
+
+ >
+ )
+}
+
+export default ArticlesScreen
diff --git a/client/web/src/components/screen/insights.jsx b/client/web/src/components/screen/insights.jsx
new file mode 100644
index 0000000..90da40f
--- /dev/null
+++ b/client/web/src/components/screen/insights.jsx
@@ -0,0 +1,160 @@
+import { useEffect } from "react"
+import { useLocation } from "wouter"
+import { useMutation, useQueryClient } from "@tanstack/react-query"
+import { Files } from "lucide-react"
+import { ArticleList } from "@/components/article-list"
+import { Button } from "@/components/ui/button"
+import { Toaster } from "@/components/ui/toaster"
+import { ButtonLoading } from "@/components/ui/button-loading"
+import { useToast } from "@/components/ui/use-toast"
+import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
+import { useClientStore, useInsights, unlinkArticle, useInsightDates, useDatePager, more } from "@/store"
+
+function List({ insights, selected, onOpen, onDelete, onReport, onMore, isGettingMore, error }) {
+ function change(value) {
+ if (value) onOpen(value)
+ }
+
+ function unlink(article_id) {
+ onDelete(selected, article_id)
+ }
+
+ return (
+
+ {insights.map((insight, i) => (
+
+
+
+ {selected === insight.id &&
}
+
{insight.content}
+
+
+ x {insight.expand.articles.length}
+
+
+
+
+
+ {error && {error.message}
}
+
+ {(isGettingMore && ) || (
+
+
+ 生成报告
+
+
+ 搜索更多
+
+
+ )}
+
+
+ ))}
+
+ )
+}
+
+function InsightsScreen({}) {
+ const selectedInsight = useClientStore((state) => state.selectedInsight)
+ const selectInsight = useClientStore((state) => state.selectInsight)
+ const dates = useInsightDates()
+ const { index, last, next, hasLast, hasNext } = useDatePager(dates)
+ // console.log(dates, index)
+ const currentDate = dates.length > 0 && index >= 0 ? dates[index] : ""
+ const data = useInsights(currentDate)
+ // console.log(data)
+ const [, navigate] = useLocation()
+ const queryClient = useQueryClient()
+ const mut = useMutation({
+ mutationFn: (data) => {
+ if (data && selectInsight && data.find((insight) => insight.id == selectedInsight).expand.articles.length == 1) {
+ throw new Error("不能删除最后一篇文章")
+ }
+ return unlinkArticle(data)
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ["insights", currentDate] })
+ },
+ })
+
+ const mutMore = useMutation({
+ mutationFn: (data) => {
+ return more(data)
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ["insights", currentDate] })
+ },
+ })
+
+ const { toast } = useToast()
+ const queryCache = queryClient.getQueryCache()
+ queryCache.onError = (error) => {
+ console.log("error in cache", error)
+ toast({
+ variant: "destructive",
+ title: "出错啦!",
+ description: error.message,
+ })
+ }
+
+ useEffect(() => {
+ selectInsight(null)
+ }, [index])
+
+ useEffect(() => {
+ mut.reset() // only show error with the selected insight
+ }, [selectedInsight])
+
+ function unlink(insight_id, article_id) {
+ mut.mutate({ insight_id, article_id })
+ }
+
+ function report() {
+ navigate("/report/" + selectedInsight)
+ }
+
+ function getMore() {
+ console.log()
+ mutMore.mutate({ insight_id: selectedInsight })
+ }
+
+ return (
+ <>
+ 分析结果
+ {currentDate && (
+
+
+ <
+
+
{currentDate}
+
+ >
+
+
+ )}
+ {data && (
+
+
+
+
+ selectInsight(id)} onDelete={unlink} onReport={report} onMore={getMore} isGettingMore={mutMore.isPending} error={mut.error} />
+
+
共{Object.keys(data).length}条结果
+
+
+ )}
+
+ >
+ )
+}
+
+export default InsightsScreen
diff --git a/client/web/src/components/screen/login.jsx b/client/web/src/components/screen/login.jsx
new file mode 100644
index 0000000..3daf1c3
--- /dev/null
+++ b/client/web/src/components/screen/login.jsx
@@ -0,0 +1,82 @@
+// import { zodResolver } from '@hookform/resolvers/zod'
+import { useForm } from 'react-hook-form'
+// import * as z from 'zod'
+import { useMutation } from '@tanstack/react-query'
+
+import { Button } from '@/components/ui/button'
+import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
+import { Input } from '@/components/ui/input'
+
+import { useLocation } from 'wouter'
+import { login } from '@/store'
+
+// const FormSchema = z.object({
+// username: z.string().nonempty('请填写用户名'),
+// password: z.string().nonempty('请填写密码'),
+// })
+
+export function AdminLoginScreen() {
+ const form = useForm({
+ // resolver: zodResolver(FormSchema),
+ defaultValues: {
+ username: '',
+ password: '',
+ },
+ })
+
+ const [, setLocation] = useLocation()
+ const mutation = useMutation({
+ mutationFn: login,
+ onSuccess: (data) => {
+ setLocation('/')
+ },
+ })
+
+ function onSubmit(e) {
+ mutation.mutate({ username: form.getValues('username'), password: form.getValues('password') })
+ }
+
+ return (
+
+ )
+}
+
+export default AdminLoginScreen
diff --git a/client/web/src/components/screen/report.jsx b/client/web/src/components/screen/report.jsx
new file mode 100644
index 0000000..6ba4f52
--- /dev/null
+++ b/client/web/src/components/screen/report.jsx
@@ -0,0 +1,98 @@
+import { useMutation, useQueryClient } from "@tanstack/react-query"
+import { Button } from "@/components/ui/button"
+import { Textarea } from "@/components/ui/textarea"
+import { Input } from "@/components/ui/input"
+import { ButtonLoading } from "@/components/ui/button-loading"
+import { FileDown } from "lucide-react"
+import { useClientStore, report, useInsight } from "@/store"
+import { useEffect } from "react"
+import { useLocation, useParams } from "wouter"
+
+function ReportScreen({}) {
+ // const selectedInsight = useClientStore((state) => state.selectedInsight)
+ // const workflow_name = useClientStore((state) => state.workflow_name)
+ // const taskId = useClientStore((state) => state.taskId)
+ // const [wasWorking, setWasWorking] = useState(false)
+
+ const toc = useClientStore((state) => state.toc)
+ const updateToc = useClientStore((state) => state.updateToc)
+ const comment = useClientStore((state) => state.comment)
+ const updateComment = useClientStore((state) => state.updateComment)
+
+ const [, navigate] = useLocation()
+ const params = useParams()
+
+ useEffect(() => {
+ if (!params || !params.insight_id) {
+ console.log("expect /report/[insight_id]")
+ navigate("/insights", { replace: true })
+ }
+ }, [])
+
+ const query = useInsight(params.insight_id)
+ const queryClient = useQueryClient()
+
+ const mut = useMutation({
+ mutationFn: async (data) => report(data),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ["insight", params.insight_id] })
+ },
+ })
+
+ function changeToc(e) {
+ let lines = e.target.value.split("\n")
+ if (lines.length == 1 && lines[0] == "") lines = []
+ // updateToc(lines.filter((l) => l.trim()))
+ updateToc(lines)
+ }
+
+ function changeComment(e) {
+ updateComment(e.target.value)
+ }
+
+ function submit(e) {
+ mut.mutate({ toc: toc, insight_id: params.insight_id, comment: comment })
+ }
+
+ return (
+ <>
+
+
已选择分析结果:
+ {query.data &&
{query.data.content}
}
+
+
+
报告大纲:
+
+ 首行输入标题,每个纲目或章节单独一行. 首行空白自动生成标题.
+ {query.data?.docx && }
+
+
+ {(mut.isPending && ) || (
+
+ {query.data?.docx ? "再次生成" : "生成"}
+
+ )}
+ {!mut.isPending && (
+ navigate("/insights")}>
+ 选择其他分析结果
+
+ )}
+
+ {!mut.isPending && query.data?.docx && (
+
+ )}
+ {query.isError && {query.error.message}
}
+ {mut.isError && {mut.error.message}
}
+ >
+ )
+}
+
+export default ReportScreen
diff --git a/client/web/src/components/screen/start.jsx b/client/web/src/components/screen/start.jsx
new file mode 100644
index 0000000..982c743
--- /dev/null
+++ b/client/web/src/components/screen/start.jsx
@@ -0,0 +1,58 @@
+import { Textarea } from "@/components/ui/textarea"
+import { Label } from "@/components/ui/label"
+import { Button } from "@/components/ui/button"
+import { ButtonLoading } from "@/components/ui/button-loading"
+import { useMutation } from "@tanstack/react-query"
+import { Minus, Plus, Loader2 } from "lucide-react"
+import { useClientStore, createTask } from "@/store"
+
+function StartScreen({ navigate, id }) {
+ const s = useClientStore()
+ const mut = useMutation({
+ mutationFn: (data) => createTask(data),
+ onSuccess: () => {
+ //query.invalidate()
+ navigate("/articles")
+ },
+ })
+
+ function change(e) {
+ let urls = e.target.value.split("\n")
+ if (urls.length == 1 && urls[0] == "") urls = []
+ s.setUrls(urls)
+ }
+
+ function submit() {
+ mut.mutate({ urls: s.urls, days: s.days })
+ }
+
+ return (
+ <>
+
+
网站清单
+
+ {s.countUrls() > 0 &&
共{s.countUrls()}个网站
}
+
+ 仅抓取
+
+
+
+
{s.days}
+
+
+
+ 天内更新的文章
+
+
+ {mut.isError && {mut.error.message}
}
+ {(mut.isPending && ) || (
+
+ {mut.isLoading && }
+ 提交
+
+ )}
+ >
+ )
+}
+
+export default StartScreen
diff --git a/client/web/src/components/screen/steps.jsx b/client/web/src/components/screen/steps.jsx
new file mode 100644
index 0000000..2a4b026
--- /dev/null
+++ b/client/web/src/components/screen/steps.jsx
@@ -0,0 +1,105 @@
+import { useState, useTransition } from "react"
+import { Banner } from "@/components/ui/banner"
+import StepLayout from "@/components/layout/step"
+import StartScreen from "@/components/screen/start"
+import ArticlesScreen from "@/components/screen/articles"
+import InsightsScreen from "@/components/screen/insights"
+import ReportScreen from "@/components/screen/report"
+
+import { Loader2 } from "lucide-react"
+import { useEffect } from "react"
+import { useClientStore, useData } from "@/store"
+
+const TITLE = "情报分析"
+
+function Steps() {
+ let [currentScreen, setCurrentScreen] = useState("/insights")
+ const [isPending, startTransition] = useTransition()
+ const selectInsight = useClientStore((state) => state.selectInsight)
+ const selectedInsight = useClientStore((state) => state.selectedInsight)
+ const taskId = useClientStore((state) => state.taskId)
+ const setTaskId = useClientStore((state) => state.setTaskId)
+
+ // useEffect(() => {
+ // const searchParams = new URLSearchParams(document.location.search)
+ // let taskIdSpecified = searchParams.get("task_id")
+ // if (taskIdSpecified) {
+ // setTaskId(taskIdSpecified)
+ // }
+ // }, [])
+
+ // const query = useData(taskId)
+ // console.log(taskId, query.data)
+
+ // useEffect(() => {
+ // // navigate away from /start
+ // if (query.data && currentScreen == "/start") {
+ // let state = query.data
+ // if (state.articles && Object.keys(state.articles).length > 0) {
+ // setCurrentScreen("/articles")
+ // }
+
+ // if (state.insights && Object.keys(state.insights).length > 0) {
+ // if (selectedInsight && state.insights[selectedInsight]?.report?.file) {
+ // setCurrentScreen("/report")
+ // } else {
+ // setCurrentScreen("/insights")
+ // }
+ // } else {
+ // selectInsight(null) // deselect
+ // }
+ // }
+ // }, [query.data])
+
+ // const errors = (query.isError && [query.error]) || (query.data && query.data.errors && query.data.errors.length > 0 && query.data.errors)
+
+ function navigate(screen) {
+ startTransition(() => {
+ setCurrentScreen(screen)
+ })
+ }
+
+ // console.log("screen:", currenScreen)
+
+ let content, title
+ if (currentScreen == "/start") {
+ title = TITLE + " > " + "数据来源"
+ content =
+ } else if (currentScreen == "/articles") {
+ title = TITLE + " > " + "文章列表"
+ content =
+ } else if (currentScreen == "/insights") {
+ title = TITLE + " > " + "分析结果"
+ content =
+ } else if (currentScreen == "/report") {
+ title = TITLE + " > " + "生成报告"
+ content =
+ }
+
+ return (
+
+ {content}
+ {/* {errors && (
+
+ {errors.map((e, i) => (
+ {e}
+ ))}
+
+ )} */}
+
+ {/* {query.data && query.data.working && (
+
+
+
+ )} */}
+ {/* {query.isFetching && (
+
+
+
+ )} */}
+ {/* task_id:{taskId}
*/}
+
+ )
+}
+
+export default Steps
diff --git a/client/web/src/components/ui/accordion.jsx b/client/web/src/components/ui/accordion.jsx
new file mode 100644
index 0000000..1f8e5ce
--- /dev/null
+++ b/client/web/src/components/ui/accordion.jsx
@@ -0,0 +1,41 @@
+import * as React from "react"
+import * as AccordionPrimitive from "@radix-ui/react-accordion"
+import { ChevronDown } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+const Accordion = AccordionPrimitive.Root
+
+const AccordionItem = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+AccordionItem.displayName = "AccordionItem"
+
+const AccordionTrigger = React.forwardRef(({ className, children, ...props }, ref) => (
+
+ svg]:rotate-180",
+ className
+ )}
+ {...props}>
+ {children}
+
+
+
+))
+AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
+
+const AccordionContent = React.forwardRef(({ className, children, ...props }, ref) => (
+
+ {children}
+
+))
+
+AccordionContent.displayName = AccordionPrimitive.Content.displayName
+
+export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
diff --git a/client/web/src/components/ui/banner.jsx b/client/web/src/components/ui/banner.jsx
new file mode 100644
index 0000000..75c11d0
--- /dev/null
+++ b/client/web/src/components/ui/banner.jsx
@@ -0,0 +1,9 @@
+import * as React from "react"
+import { cn } from "@/lib/utils"
+
+const Banner = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+Banner.displayName = "Banner"
+
+export { Banner }
diff --git a/client/web/src/components/ui/button-loading.jsx b/client/web/src/components/ui/button-loading.jsx
new file mode 100644
index 0000000..69994d1
--- /dev/null
+++ b/client/web/src/components/ui/button-loading.jsx
@@ -0,0 +1,11 @@
+import { Button } from '@/components/ui/button'
+import { Loader2 } from 'lucide-react'
+
+export function ButtonLoading() {
+ return (
+
+
+ 请稍后
+
+ )
+}
diff --git a/client/web/src/components/ui/button.jsx b/client/web/src/components/ui/button.jsx
new file mode 100644
index 0000000..9bdf65b
--- /dev/null
+++ b/client/web/src/components/ui/button.jsx
@@ -0,0 +1,47 @@
+import * as React from "react"
+import { Slot } from "@radix-ui/react-slot"
+import { cva } from "class-variance-authority";
+
+import { cn } from "@/lib/utils"
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-destructive-foreground hover:bg-destructive/90",
+ outline:
+ "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
+ secondary:
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default: "h-10 px-4 py-2",
+ sm: "h-9 rounded-md px-3",
+ lg: "h-11 rounded-md px-8",
+ icon: "h-10 w-10",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+)
+
+const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : "button"
+ return (
+ ( )
+ );
+})
+Button.displayName = "Button"
+
+export { Button, buttonVariants }
diff --git a/client/web/src/components/ui/form.jsx b/client/web/src/components/ui/form.jsx
new file mode 100644
index 0000000..5275c62
--- /dev/null
+++ b/client/web/src/components/ui/form.jsx
@@ -0,0 +1,133 @@
+import * as React from "react"
+import { Slot } from "@radix-ui/react-slot"
+import { Controller, FormProvider, useFormContext } from "react-hook-form";
+
+import { cn } from "@/lib/utils"
+import { Label } from "@/components/ui/label"
+
+const Form = FormProvider
+
+const FormFieldContext = React.createContext({})
+
+const FormField = (
+ {
+ ...props
+ }
+) => {
+ return (
+ (
+
+ )
+ );
+}
+
+const useFormField = () => {
+ const fieldContext = React.useContext(FormFieldContext)
+ const itemContext = React.useContext(FormItemContext)
+ const { getFieldState, formState } = useFormContext()
+
+ const fieldState = getFieldState(fieldContext.name, formState)
+
+ if (!fieldContext) {
+ throw new Error("useFormField should be used within ")
+ }
+
+ const { id } = itemContext
+
+ return {
+ id,
+ name: fieldContext.name,
+ formItemId: `${id}-form-item`,
+ formDescriptionId: `${id}-form-item-description`,
+ formMessageId: `${id}-form-item-message`,
+ ...fieldState,
+ }
+}
+
+const FormItemContext = React.createContext({})
+
+const FormItem = React.forwardRef(({ className, ...props }, ref) => {
+ const id = React.useId()
+
+ return (
+ (
+
+ )
+ );
+})
+FormItem.displayName = "FormItem"
+
+const FormLabel = React.forwardRef(({ className, ...props }, ref) => {
+ const { error, formItemId } = useFormField()
+
+ return (
+ ( )
+ );
+})
+FormLabel.displayName = "FormLabel"
+
+const FormControl = React.forwardRef(({ ...props }, ref) => {
+ const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
+
+ return (
+ ( )
+ );
+})
+FormControl.displayName = "FormControl"
+
+const FormDescription = React.forwardRef(({ className, ...props }, ref) => {
+ const { formDescriptionId } = useFormField()
+
+ return (
+ (
)
+ );
+})
+FormDescription.displayName = "FormDescription"
+
+const FormMessage = React.forwardRef(({ className, children, ...props }, ref) => {
+ const { error, formMessageId } = useFormField()
+ const body = error ? String(error?.message) : children
+
+ if (!body) {
+ return null
+ }
+
+ return (
+ (
+ {body}
+
)
+ );
+})
+FormMessage.displayName = "FormMessage"
+
+export {
+ useFormField,
+ Form,
+ FormItem,
+ FormLabel,
+ FormControl,
+ FormDescription,
+ FormMessage,
+ FormField,
+}
diff --git a/client/web/src/components/ui/input.jsx b/client/web/src/components/ui/input.jsx
new file mode 100644
index 0000000..c74d919
--- /dev/null
+++ b/client/web/src/components/ui/input.jsx
@@ -0,0 +1,19 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Input = React.forwardRef(({ className, type, ...props }, ref) => {
+ return (
+ ( )
+ );
+})
+Input.displayName = "Input"
+
+export { Input }
diff --git a/client/web/src/components/ui/label.jsx b/client/web/src/components/ui/label.jsx
new file mode 100644
index 0000000..a1f4099
--- /dev/null
+++ b/client/web/src/components/ui/label.jsx
@@ -0,0 +1,16 @@
+import * as React from "react"
+import * as LabelPrimitive from "@radix-ui/react-label"
+import { cva } from "class-variance-authority";
+
+import { cn } from "@/lib/utils"
+
+const labelVariants = cva(
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
+)
+
+const Label = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+Label.displayName = LabelPrimitive.Root.displayName
+
+export { Label }
diff --git a/client/web/src/components/ui/textarea.jsx b/client/web/src/components/ui/textarea.jsx
new file mode 100644
index 0000000..7369cf5
--- /dev/null
+++ b/client/web/src/components/ui/textarea.jsx
@@ -0,0 +1,18 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Textarea = React.forwardRef(({ className, ...props }, ref) => {
+ return (
+ ()
+ );
+})
+Textarea.displayName = "Textarea"
+
+export { Textarea }
diff --git a/client/web/src/components/ui/toast.jsx b/client/web/src/components/ui/toast.jsx
new file mode 100644
index 0000000..c95bc40
--- /dev/null
+++ b/client/web/src/components/ui/toast.jsx
@@ -0,0 +1,82 @@
+import * as React from "react"
+import * as ToastPrimitives from "@radix-ui/react-toast"
+import { cva } from "class-variance-authority";
+import { X } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+const ToastProvider = ToastPrimitives.Provider
+
+const ToastViewport = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+ToastViewport.displayName = ToastPrimitives.Viewport.displayName
+
+const toastVariants = cva(
+ "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
+ {
+ variants: {
+ variant: {
+ default: "border bg-background text-foreground",
+ destructive:
+ "destructive group border-destructive bg-destructive text-destructive-foreground",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ }
+)
+
+const Toast = React.forwardRef(({ className, variant, ...props }, ref) => {
+ return (
+ ( )
+ );
+})
+Toast.displayName = ToastPrimitives.Root.displayName
+
+const ToastAction = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+ToastAction.displayName = ToastPrimitives.Action.displayName
+
+const ToastClose = React.forwardRef(({ className, ...props }, ref) => (
+
+
+
+))
+ToastClose.displayName = ToastPrimitives.Close.displayName
+
+const ToastTitle = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+ToastTitle.displayName = ToastPrimitives.Title.displayName
+
+const ToastDescription = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+ToastDescription.displayName = ToastPrimitives.Description.displayName
+
+export { ToastProvider, ToastViewport, Toast, ToastTitle, ToastDescription, ToastClose, ToastAction };
diff --git a/client/web/src/components/ui/toaster.jsx b/client/web/src/components/ui/toaster.jsx
new file mode 100644
index 0000000..b7a9a25
--- /dev/null
+++ b/client/web/src/components/ui/toaster.jsx
@@ -0,0 +1,33 @@
+import {
+ Toast,
+ ToastClose,
+ ToastDescription,
+ ToastProvider,
+ ToastTitle,
+ ToastViewport,
+} from "@/components/ui/toast"
+import { useToast } from "@/components/ui/use-toast"
+
+export function Toaster() {
+ const { toasts } = useToast()
+
+ return (
+ (
+ {toasts.map(function ({ id, title, description, action, ...props }) {
+ return (
+ (
+
+ {title && {title} }
+ {description && (
+ {description}
+ )}
+
+ {action}
+
+ )
+ );
+ })}
+
+ )
+ );
+}
diff --git a/client/web/src/components/ui/use-toast.js b/client/web/src/components/ui/use-toast.js
new file mode 100644
index 0000000..df6b786
--- /dev/null
+++ b/client/web/src/components/ui/use-toast.js
@@ -0,0 +1,154 @@
+// Inspired by react-hot-toast library
+import * as React from "react"
+
+const TOAST_LIMIT = 1
+const TOAST_REMOVE_DELAY = 1000000
+
+const actionTypes = {
+ ADD_TOAST: "ADD_TOAST",
+ UPDATE_TOAST: "UPDATE_TOAST",
+ DISMISS_TOAST: "DISMISS_TOAST",
+ REMOVE_TOAST: "REMOVE_TOAST"
+}
+
+let count = 0
+
+function genId() {
+ count = (count + 1) % Number.MAX_SAFE_INTEGER
+ return count.toString();
+}
+
+const toastTimeouts = new Map()
+
+const addToRemoveQueue = (toastId) => {
+ if (toastTimeouts.has(toastId)) {
+ return
+ }
+
+ const timeout = setTimeout(() => {
+ toastTimeouts.delete(toastId)
+ dispatch({
+ type: "REMOVE_TOAST",
+ toastId: toastId,
+ })
+ }, TOAST_REMOVE_DELAY)
+
+ toastTimeouts.set(toastId, timeout)
+}
+
+export const reducer = (state, action) => {
+ switch (action.type) {
+ case "ADD_TOAST":
+ return {
+ ...state,
+ toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
+ };
+
+ case "UPDATE_TOAST":
+ return {
+ ...state,
+ toasts: state.toasts.map((t) =>
+ t.id === action.toast.id ? { ...t, ...action.toast } : t),
+ };
+
+ case "DISMISS_TOAST": {
+ const { toastId } = action
+
+ // ! Side effects ! - This could be extracted into a dismissToast() action,
+ // but I'll keep it here for simplicity
+ if (toastId) {
+ addToRemoveQueue(toastId)
+ } else {
+ state.toasts.forEach((toast) => {
+ addToRemoveQueue(toast.id)
+ })
+ }
+
+ return {
+ ...state,
+ toasts: state.toasts.map((t) =>
+ t.id === toastId || toastId === undefined
+ ? {
+ ...t,
+ open: false,
+ }
+ : t),
+ };
+ }
+ case "REMOVE_TOAST":
+ if (action.toastId === undefined) {
+ return {
+ ...state,
+ toasts: [],
+ }
+ }
+ return {
+ ...state,
+ toasts: state.toasts.filter((t) => t.id !== action.toastId),
+ };
+ }
+}
+
+const listeners = []
+
+let memoryState = { toasts: [] }
+
+function dispatch(action) {
+ memoryState = reducer(memoryState, action)
+ listeners.forEach((listener) => {
+ listener(memoryState)
+ })
+}
+
+function toast({
+ ...props
+}) {
+ const id = genId()
+
+ const update = (props) =>
+ dispatch({
+ type: "UPDATE_TOAST",
+ toast: { ...props, id },
+ })
+ const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
+
+ dispatch({
+ type: "ADD_TOAST",
+ toast: {
+ ...props,
+ id,
+ open: true,
+ onOpenChange: (open) => {
+ if (!open) dismiss()
+ },
+ },
+ })
+
+ return {
+ id: id,
+ dismiss,
+ update,
+ }
+}
+
+function useToast() {
+ const [state, setState] = React.useState(memoryState)
+
+ React.useEffect(() => {
+ listeners.push(setState)
+ return () => {
+ const index = listeners.indexOf(setState)
+ if (index > -1) {
+ listeners.splice(index, 1)
+ }
+ };
+ }, [state])
+
+ return {
+ ...state,
+ toast,
+ dismiss: (toastId) => dispatch({ type: "DISMISS_TOAST", toastId }),
+ };
+}
+
+export { useToast, toast }
diff --git a/client/web/src/index.css b/client/web/src/index.css
new file mode 100644
index 0000000..b55d994
--- /dev/null
+++ b/client/web/src/index.css
@@ -0,0 +1,82 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ :root {
+ --background: 0 0% 100%;
+ --foreground: 222.2 84% 4.9%;
+
+ --card: 0 0% 100%;
+ --card-foreground: 222.2 84% 4.9%;
+
+ --popover: 0 0% 100%;
+ --popover-foreground: 222.2 84% 4.9%;
+
+ --primary: 222.2 47.4% 11.2%;
+ --primary-foreground: 210 40% 98%;
+
+ --secondary: 210 40% 96.1%;
+ --secondary-foreground: 222.2 47.4% 11.2%;
+
+ --muted: 210 40% 96.1%;
+ --muted-foreground: 215.4 16.3% 46.9%;
+
+ --accent: 210 40% 96.1%;
+ --accent-foreground: 222.2 47.4% 11.2%;
+
+ --destructive: 0 84.2% 60.2%;
+ --destructive-foreground: 210 40% 98%;
+
+ --border: 214.3 31.8% 91.4%;
+ --input: 214.3 31.8% 91.4%;
+ --ring: 222.2 84% 4.9%;
+
+ --radius: 0.5rem;
+ }
+
+ .dark {
+ --background: 222.2 84% 4.9%;
+ --foreground: 210 40% 98%;
+
+ --card: 222.2 84% 4.9%;
+ --card-foreground: 210 40% 98%;
+
+ --popover: 222.2 84% 4.9%;
+ --popover-foreground: 210 40% 98%;
+
+ --primary: 210 40% 98%;
+ --primary-foreground: 222.2 47.4% 11.2%;
+
+ --secondary: 217.2 32.6% 17.5%;
+ --secondary-foreground: 210 40% 98%;
+
+ --muted: 217.2 32.6% 17.5%;
+ --muted-foreground: 215 20.2% 65.1%;
+
+ --accent: 217.2 32.6% 17.5%;
+ --accent-foreground: 210 40% 98%;
+
+ --destructive: 0 62.8% 30.6%;
+ --destructive-foreground: 210 40% 98%;
+
+ --border: 217.2 32.6% 17.5%;
+ --input: 217.2 32.6% 17.5%;
+ --ring: 212.7 26.8% 83.9%;
+ }
+}
+
+@layer base {
+ * {
+ @apply border-border;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
+
+@layer components {
+ h2 {
+ @apply scroll-m-20 text-2xl font-semibold tracking-tight mb-4;
+ }
+}
diff --git a/client/web/src/lib/utils.js b/client/web/src/lib/utils.js
new file mode 100644
index 0000000..d314d8c
--- /dev/null
+++ b/client/web/src/lib/utils.js
@@ -0,0 +1,18 @@
+import { clsx } from "clsx"
+import { twMerge } from "tailwind-merge"
+
+export function cn(...inputs) {
+ return twMerge(clsx(inputs))
+}
+
+export function formatDate(date) {
+ var d = new Date(isNaN(date) ? date + "T00:00:00" : date)
+ var iso = d.toISOString()
+ return iso.slice(0, 10) + " " + iso.slice(11, 23) + "Z"
+ // return [d.getFullYear(), (d.getMonth() + 1).padLeft(), d.getDate().padLeft()].join("-") + " " + [d.getHours().padLeft(), d.getMinutes().padLeft(), d.getSeconds().padLeft()].join(":") + ".000Z"
+}
+
+Number.prototype.padLeft = function (base, chr) {
+ var len = String(base || 10).length - String(this).length + 1
+ return len > 0 ? new Array(len).join(chr || "0") + this : this
+}
diff --git a/client/web/src/main.jsx b/client/web/src/main.jsx
new file mode 100644
index 0000000..54b39dd
--- /dev/null
+++ b/client/web/src/main.jsx
@@ -0,0 +1,10 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App.jsx'
+import './index.css'
+
+ReactDOM.createRoot(document.getElementById('root')).render(
+
+
+ ,
+)
diff --git a/client/web/src/store.js b/client/web/src/store.js
new file mode 100644
index 0000000..be5fb65
--- /dev/null
+++ b/client/web/src/store.js
@@ -0,0 +1,273 @@
+import { useEffect, useState } from "react"
+import PocketBase from "pocketbase"
+const pb = new PocketBase(import.meta.env.VITE_PB_BASE)
+import { useQuery } from "@tanstack/react-query"
+
+import { create } from "zustand"
+import { persist } from "zustand/middleware"
+// import axios from "redaxios"
+import axios from "axios"
+import { nanoid } from "nanoid"
+
+import { formatDate } from "./lib/utils"
+
+const DAYS_RANGE = [1, 14]
+
+export const useClientStore = create(
+ persist(
+ (set, get) => ({
+ taskId: "",
+ urls: ["https://cyberscoop.com"],
+ days: 14,
+ workflow_name: "情报分析",
+ toc: ["参考情报", "基本内容", "相关发声情况", "应对策略"],
+ selectedInsight: null,
+ comment: "",
+
+ setTaskId: (taskId) => set({ taskId }),
+ setUrls: (urls) => set({ urls }),
+ countUrls: () => get().urls.filter((url) => url).length,
+ selectInsight: (id) => set({ selectedInsight: id }),
+ updateToc: (value) => set({ toc: value }),
+ updateComment: (value) => set({ comment: value }),
+ incr: () => set((state) => ({ days: state.days + 1 > DAYS_RANGE[1] ? DAYS_RANGE[1] : state.days + 1 })),
+ decr: () => set((state) => ({ days: state.days - 1 < DAYS_RANGE[0] ? DAYS_RANGE[0] : state.days - 1 })),
+ minDays: () => get().days === DAYS_RANGE[0],
+ maxDays: () => get().days === DAYS_RANGE[1],
+ }),
+ {
+ version: "0.1.1",
+ name: "aw-storage",
+ // storage: createJSONStorage(() => sessionStorage), // (optional) by default, 'localStorage' is used
+ }
+ )
+)
+
+export function login({ username, password }) {
+ //return pb.collection("users").authWithPassword(username, password)
+ return pb.admins.authWithPassword(username, password)
+}
+
+export function isAuth() {
+ return pb.authStore.isValid
+}
+
+export function useData(task_id, autoRefetch = undefined) {
+ let interval = parseInt(autoRefetch) >= 1000 ? parseInt(autoRefetch) : undefined
+
+ return useQuery({
+ queryKey: ["data", task_id ? task_id : ""],
+ queryFn: () => data(task_id ? task_id : ""),
+ refetchInterval: (query) => {
+ //console.log(query)
+ if (!query.state.data || (query.state.data && query.state.data.working)) {
+ return interval
+ }
+ return undefined
+ },
+ })
+}
+
+export function createTask({ id, urls, days }) {
+ let from = new Date()
+ from.setHours(0, 0, 0, 0)
+ from.setDate(from.getDate() - days)
+
+ let fromStr = from.toISOString().slice(0, 10).split("-").join("")
+ let task_id = id || nanoid(10)
+ console.log("creating task: ", task_id, urls.filter((url) => url).length + " sites", fromStr)
+
+ if (urls.length == 0) {
+ urls.push("")
+ }
+
+ return axios({
+ method: "post",
+ url: `${import.meta.env.VITE_API_BASE}/sites`,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ data: {
+ after: fromStr,
+ sites: urls,
+ task_id: task_id,
+ },
+ })
+ .then(function (response) {
+ useClientStore.getState().setTaskId(task_id)
+ return response
+ })
+ .catch(function (error) {
+ useClientStore.getState().setTaskId("")
+ return error
+ })
+}
+
+export function report({ task_id, insight_id, toc, comment }) {
+ return axios({
+ method: "post",
+ url: `${import.meta.env.VITE_API_BASE}/report`,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ data: {
+ task_id: task_id,
+ toc: toc,
+ insight_id: insight_id,
+ comment: comment,
+ },
+ })
+}
+
+export function more({ insight_id }) {
+ return axios({
+ method: "post",
+ url: `${import.meta.env.VITE_API_BASE}/search_for_insight`,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ data: {
+ //toc: toc,
+ insight_id: insight_id,
+ //comment: comment,
+ },
+ })
+}
+
+export function translations({ article_ids }) {
+ return axios({
+ method: "post",
+ url: `${import.meta.env.VITE_API_BASE}/translations`,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ data: {
+ article_ids,
+ },
+ })
+}
+
+export function useArticles(date) {
+ return useQuery({
+ queryKey: ["articles", date],
+ queryFn: () => getArticles(date),
+ })
+}
+
+export function useInsight(id) {
+ return useQuery({
+ queryKey: ["insight", id],
+ queryFn: () => getInsight(id),
+ })
+}
+
+export function useInsights(date) {
+ const { data = [] } = useQuery({
+ queryKey: ["insights", date],
+ queryFn: () => getInsights(date),
+ })
+ return data
+}
+
+export function useInsightDates() {
+ const { data = [] } = useQuery({
+ queryKey: ["insight_dates"],
+ queryFn: getInsightDates,
+ })
+ return data
+}
+
+export function useArticleDates() {
+ return useQuery({
+ queryKey: ["article_dates"],
+ queryFn: () => getArticleDates(),
+ })
+}
+
+export function useDatePager(dates) {
+ const [index, setIndex] = useState(-1)
+
+ useEffect(() => {
+ if (index < 0 && dates) {
+ setIndex(dates.length - 1)
+ }
+ }, [index, dates])
+
+ const hasLast = () => index > 0
+ const hasNext = () => index >= 0 && index < dates.length - 1
+ const last = () => hasLast() && setIndex(index - 1)
+ const next = () => hasNext() && setIndex(index + 1)
+
+ return {
+ index,
+ last,
+ next,
+ hasLast,
+ hasNext,
+ }
+}
+
+export function getArticles(date) {
+ if (!date) return []
+
+ const from = formatDate(date)
+ const to = formatDate(new Date(new Date(date).getTime() + 60 * 60 * 24 * 1000))
+ return pb.collection("articles").getFullList({
+ sort: "-created",
+ expand: "translation_result",
+ filter: 'created >= "' + from + '" && created < "' + to + '"',
+ })
+}
+
+export function getInsight(id) {
+ return pb.collection("insights").getOne(id, { expand: "docx" })
+}
+
+export function getInsights(date) {
+ if (!date) return null
+
+ const from = formatDate(date)
+ const to = formatDate(new Date(new Date(date + "T00:00:00").getTime() + 60 * 60 * 24 * 1000))
+ // console.log("from/to", from, to)
+
+ const f = 'created >= "' + from + '" && created < "' + to + '"'
+ console.log(f)
+
+ return pb.collection("insights").getFullList({
+ sort: "-created",
+ expand: "articles, articles.translation_result",
+ // expand: "articles",
+ filter: f,
+ })
+}
+
+export async function getInsightDates() {
+ const { data } = await axios({
+ method: "get",
+ url: `${import.meta.env.VITE_PB_BASE}/insight_dates`,
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer " + pb.authStore?.token,
+ },
+ })
+ // return data.map((d) => new Date(d + "T00:00:00Z").toLocaleDateString().split("/").join("-"))
+ return data
+}
+
+export async function getArticleDates() {
+ let { data } = await axios({
+ method: "get",
+ url: `${import.meta.env.VITE_PB_BASE}/article_dates`,
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer " + pb.authStore?.token,
+ },
+ })
+ return data
+}
+
+export function unlinkArticle({ insight_id, article_id }) {
+ return pb.collection("insights").update(insight_id, {
+ "articles-": article_id,
+ })
+}
diff --git a/client/web/tailwind.config.js b/client/web/tailwind.config.js
new file mode 100644
index 0000000..0a5fa43
--- /dev/null
+++ b/client/web/tailwind.config.js
@@ -0,0 +1,77 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ darkMode: ["class"],
+ content: [
+ './pages/**/*.{js,jsx}',
+ './components/**/*.{js,jsx}',
+ './app/**/*.{js,jsx}',
+ './src/**/*.{js,jsx}',
+ ],
+ prefix: "",
+ theme: {
+ container: {
+ center: true,
+ padding: "2rem",
+ screens: {
+ "2xl": "1400px",
+ },
+ },
+ extend: {
+ colors: {
+ border: "hsl(var(--border))",
+ input: "hsl(var(--input))",
+ ring: "hsl(var(--ring))",
+ background: "hsl(var(--background))",
+ foreground: "hsl(var(--foreground))",
+ primary: {
+ DEFAULT: "hsl(var(--primary))",
+ foreground: "hsl(var(--primary-foreground))",
+ },
+ secondary: {
+ DEFAULT: "hsl(var(--secondary))",
+ foreground: "hsl(var(--secondary-foreground))",
+ },
+ destructive: {
+ DEFAULT: "hsl(var(--destructive))",
+ foreground: "hsl(var(--destructive-foreground))",
+ },
+ muted: {
+ DEFAULT: "hsl(var(--muted))",
+ foreground: "hsl(var(--muted-foreground))",
+ },
+ accent: {
+ DEFAULT: "hsl(var(--accent))",
+ foreground: "hsl(var(--accent-foreground))",
+ },
+ popover: {
+ DEFAULT: "hsl(var(--popover))",
+ foreground: "hsl(var(--popover-foreground))",
+ },
+ card: {
+ DEFAULT: "hsl(var(--card))",
+ foreground: "hsl(var(--card-foreground))",
+ },
+ },
+ borderRadius: {
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)",
+ },
+ keyframes: {
+ "accordion-down": {
+ from: { height: "0" },
+ to: { height: "var(--radix-accordion-content-height)" },
+ },
+ "accordion-up": {
+ from: { height: "var(--radix-accordion-content-height)" },
+ to: { height: "0" },
+ },
+ },
+ animation: {
+ "accordion-down": "accordion-down 0.2s ease-out",
+ "accordion-up": "accordion-up 0.2s ease-out",
+ },
+ },
+ },
+ plugins: [require("tailwindcss-animate")],
+}
\ No newline at end of file
diff --git a/client/web/tsconfig.json b/client/web/tsconfig.json
new file mode 100644
index 0000000..abe04df
--- /dev/null
+++ b/client/web/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ }
+}
diff --git a/client/web/vite.config.js b/client/web/vite.config.js
new file mode 100644
index 0000000..86bd487
--- /dev/null
+++ b/client/web/vite.config.js
@@ -0,0 +1,15 @@
+import path from "path"
+import * as child from "child_process"
+import { defineConfig } from "vite"
+import react from "@vitejs/plugin-react"
+// const commitHash = child.execSync('git rev-parse --short HEAD').toString()
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ resolve: {
+ alias: {
+ "@": path.resolve(__dirname, "./src"),
+ },
+ },
+ // define: { 'import.meta.env.VITE_APP_VERSION': JSON.stringify(commitHash) },
+})
From f3a3e72b0b65b89f4f64783d8a836ed22b19fffd Mon Sep 17 00:00:00 2001
From: Lingfei Song <82314+madcat@users.noreply.github.com>
Date: Thu, 11 Apr 2024 12:53:18 +0700
Subject: [PATCH 02/16] report layout adjustments
---
client/web/src/components/screen/articles.jsx | 2 +-
client/web/src/components/screen/report.jsx | 15 ++++++++-------
client/web/src/index.css | 2 +-
3 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/client/web/src/components/screen/articles.jsx b/client/web/src/components/screen/articles.jsx
index 2c3045f..05323d9 100644
--- a/client/web/src/components/screen/articles.jsx
+++ b/client/web/src/components/screen/articles.jsx
@@ -27,7 +27,7 @@ function ArticlesScreen({}) {
})
function trans() {
- mut.mutate({ article_ids: query.data.map((d) => d.id) })
+ mut.mutate({ article_ids: query.data.filter((d) => !d.translation_result).map((d) => d.id) })
}
return (
diff --git a/client/web/src/components/screen/report.jsx b/client/web/src/components/screen/report.jsx
index 6ba4f52..44b9cec 100644
--- a/client/web/src/components/screen/report.jsx
+++ b/client/web/src/components/screen/report.jsx
@@ -55,18 +55,19 @@ function ReportScreen({}) {
}
return (
- <>
+
+
报告生成
已选择分析结果:
- {query.data &&
{query.data.content}
}
+ {query.data &&
{query.data.content}
}
报告大纲:
-
+
首行输入标题,每个纲目或章节单独一行. 首行空白自动生成标题.
- {query.data?.docx && }
+ {query.data?.docx && }
-
+
{(mut.isPending && ) || (
{query.data?.docx ? "再次生成" : "生成"}
@@ -79,7 +80,7 @@ function ReportScreen({}) {
)}
{!mut.isPending && query.data?.docx && (
-
+
报告已生成,点击下载
@@ -91,7 +92,7 @@ function ReportScreen({}) {
)}
{query.isError &&
{query.error.message}
}
{mut.isError &&
{mut.error.message}
}
- >
+
)
}
diff --git a/client/web/src/index.css b/client/web/src/index.css
index b55d994..cb11880 100644
--- a/client/web/src/index.css
+++ b/client/web/src/index.css
@@ -77,6 +77,6 @@
@layer components {
h2 {
- @apply scroll-m-20 text-2xl font-semibold tracking-tight mb-4;
+ @apply scroll-m-20 text-2xl font-semibold tracking-tight mb-4 text-left;
}
}
From 5250eb837c5f23262ed42041d80709ec1a175a8d Mon Sep 17 00:00:00 2001
From: Lingfei Song <82314+madcat@users.noreply.github.com>
Date: Fri, 12 Apr 2024 11:04:07 +0700
Subject: [PATCH 03/16] page data in utc yyyy-mm-dd, not local date
---
client/Dockerfile.web | 4 +++-
client/pb/pb_hooks/main.pb.js | 2 +-
client/web/src/components/screen/insights.jsx | 6 +++---
client/web/src/lib/utils.js | 5 ++++-
client/web/src/store.js | 15 +++++++++------
5 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/client/Dockerfile.web b/client/Dockerfile.web
index d4ef67d..df59a6b 100644
--- a/client/Dockerfile.web
+++ b/client/Dockerfile.web
@@ -12,7 +12,9 @@ FROM alpine:latest
ARG PB_VERSION=0.21.1
-RUN apk add --no-cache unzip ca-certificates tzdata
+RUN apk add --no-cache unzip ca-certificates tzdata && \
+ ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
+
# download and unzip PocketBase
ADD https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_linux_amd64.zip /tmp/pb.zip
diff --git a/client/pb/pb_hooks/main.pb.js b/client/pb/pb_hooks/main.pb.js
index 44bf76a..7f585e8 100644
--- a/client/pb/pb_hooks/main.pb.js
+++ b/client/pb/pb_hooks/main.pb.js
@@ -43,7 +43,7 @@ routerAdd(
})
)
- $app.dao().db().newQuery("SELECT DISTINCT DATE(created, 'localtime') as created FROM insights").all(result)
+ $app.dao().db().newQuery("SELECT DISTINCT DATE(created) as created FROM insights").all(result)
return c.json(
200,
diff --git a/client/web/src/components/screen/insights.jsx b/client/web/src/components/screen/insights.jsx
index 90da40f..2cbbd8c 100644
--- a/client/web/src/components/screen/insights.jsx
+++ b/client/web/src/components/screen/insights.jsx
@@ -66,11 +66,11 @@ function InsightsScreen({}) {
const [, navigate] = useLocation()
const queryClient = useQueryClient()
const mut = useMutation({
- mutationFn: (data) => {
- if (data && selectInsight && data.find((insight) => insight.id == selectedInsight).expand.articles.length == 1) {
+ mutationFn: (params) => {
+ if (params && selectedInsight && data.find((insight) => insight.id == selectedInsight).expand.articles.length == 1) {
throw new Error("不能删除最后一篇文章")
}
- return unlinkArticle(data)
+ return unlinkArticle(params)
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["insights", currentDate] })
diff --git a/client/web/src/lib/utils.js b/client/web/src/lib/utils.js
index d314d8c..eae5d61 100644
--- a/client/web/src/lib/utils.js
+++ b/client/web/src/lib/utils.js
@@ -1,12 +1,15 @@
import { clsx } from "clsx"
import { twMerge } from "tailwind-merge"
+export const LOCAL_TIME_OFFSITE = "+08:00"
+
export function cn(...inputs) {
return twMerge(clsx(inputs))
}
export function formatDate(date) {
- var d = new Date(isNaN(date) ? date + "T00:00:00" : date)
+ // var d = new Date(isNaN(date) ? date + "T00:00:00" + LOCAL_TIME_OFFSITE : date) // local
+ var d = new Date(isNaN(date) ? date + "T00:00:00" : date) // utc
var iso = d.toISOString()
return iso.slice(0, 10) + " " + iso.slice(11, 23) + "Z"
// return [d.getFullYear(), (d.getMonth() + 1).padLeft(), d.getDate().padLeft()].join("-") + " " + [d.getHours().padLeft(), d.getMinutes().padLeft(), d.getSeconds().padLeft()].join(":") + ".000Z"
diff --git a/client/web/src/store.js b/client/web/src/store.js
index be5fb65..e2c08cf 100644
--- a/client/web/src/store.js
+++ b/client/web/src/store.js
@@ -9,7 +9,7 @@ import { persist } from "zustand/middleware"
import axios from "axios"
import { nanoid } from "nanoid"
-import { formatDate } from "./lib/utils"
+import { formatDate, LOCAL_TIME_OFFSITE } from "./lib/utils"
const DAYS_RANGE = [1, 14]
@@ -211,7 +211,9 @@ export function getArticles(date) {
if (!date) return []
const from = formatDate(date)
- const to = formatDate(new Date(new Date(date).getTime() + 60 * 60 * 24 * 1000))
+ //const to = formatDate(new Date(new Date(date + "T00:00:00" + LOCAL_TIME_OFFSITE).getTime() + 60 * 60 * 24 * 1000))
+ const to = formatDate(new Date(new Date(date + "T00:00:00").getTime() + 60 * 60 * 24 * 1000))
+ console.log("from/to", from, to)
return pb.collection("articles").getFullList({
sort: "-created",
expand: "translation_result",
@@ -224,15 +226,15 @@ export function getInsight(id) {
}
export function getInsights(date) {
- if (!date) return null
+ if (!date) return []
const from = formatDate(date)
+ //const to = formatDate(new Date(new Date(date + "T00:00:00" + LOCAL_TIME_OFFSITE).getTime() + 60 * 60 * 24 * 1000))
const to = formatDate(new Date(new Date(date + "T00:00:00").getTime() + 60 * 60 * 24 * 1000))
// console.log("from/to", from, to)
const f = 'created >= "' + from + '" && created < "' + to + '"'
- console.log(f)
-
+ // console.log(f)
return pb.collection("insights").getFullList({
sort: "-created",
expand: "articles, articles.translation_result",
@@ -250,7 +252,7 @@ export async function getInsightDates() {
Authorization: "Bearer " + pb.authStore?.token,
},
})
- // return data.map((d) => new Date(d + "T00:00:00Z").toLocaleDateString().split("/").join("-"))
+ //return data.map((d) => new Date(d + "T00:00:00" + LOCAL_TIME_OFFSITE).toISOString().slice(0, 10))
return data
}
@@ -263,6 +265,7 @@ export async function getArticleDates() {
Authorization: "Bearer " + pb.authStore?.token,
},
})
+ //return data.map((d) => new Date(d + "T00:00:00" + LOCAL_TIME_OFFSITE).toISOString().slice(0, 10))
return data
}
From 1d5a77536e4c43a31866c4198e09500563f374c2 Mon Sep 17 00:00:00 2001
From: bigbrother666
Date: Tue, 16 Apr 2024 08:05:49 +0800
Subject: [PATCH 04/16] resolve docker yaml
---
client/backend/requirements.txt | 17 -----------------
client/compose.yaml | 1 +
2 files changed, 1 insertion(+), 17 deletions(-)
delete mode 100644 client/backend/requirements.txt
diff --git a/client/backend/requirements.txt b/client/backend/requirements.txt
deleted file mode 100644
index e2148b6..0000000
--- a/client/backend/requirements.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-fastapi
-pydantic
-uvicorn
-dashscope #optional(使用阿里灵积时安装)
-volcengine #optional(使用火山翻译时安装)
-python-docx
-BCEmbedding==0.1.3
-langchain==0.1.0
-langchain-community==0.0.9
-langchain-core==0.1.7
-langsmith==0.0.77
-# faiss-gpu for gpu environment
-faiss-cpu # for cpu-only environment
-pocketbase==0.10.0
-gne
-selenium
-chardet
\ No newline at end of file
diff --git a/client/compose.yaml b/client/compose.yaml
index 88c0a7a..35992da 100644
--- a/client/compose.yaml
+++ b/client/compose.yaml
@@ -19,3 +19,4 @@ services:
volumes:
#- ./${PROJECT_DIR}:/app/${PROJECT_DIR}
- ${EMBEDDING_MODEL_PATH}:${EMBEDDING_MODEL_PATH}
+ - ${RERANKER_MODEL_PATH}:${RERANKER_MODEL_PATH}
From 76f69e5e26952e06b4ea6113cbb226c3a6052823 Mon Sep 17 00:00:00 2001
From: bigbrother666
Date: Tue, 16 Apr 2024 08:08:36 +0800
Subject: [PATCH 05/16] add requirements
---
client/backend/requirements.txt | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 client/backend/requirements.txt
diff --git a/client/backend/requirements.txt b/client/backend/requirements.txt
new file mode 100644
index 0000000..573c9a9
--- /dev/null
+++ b/client/backend/requirements.txt
@@ -0,0 +1,16 @@
+fastapi
+pydantic
+uvicorn
+dashscope #optional(使用阿里灵积时安装)
+volcengine #optional(使用火山翻译时安装)
+python-docx
+BCEmbedding==0.1.3
+langchain==0.1.0
+langchain-community==0.0.9
+langchain-core==0.1.7
+langsmith==0.0.77
+# faiss-gpu for gpu environment
+faiss-cpu # for cpu-only environment
+pocketbase==0.10.0
+gne
+chardet
\ No newline at end of file
From 265e1c533a90161c1efaed5afb6acfb8f1fbe6ec Mon Sep 17 00:00:00 2001
From: Lingfei Song <82314+madcat@users.noreply.github.com>
Date: Thu, 11 Apr 2024 12:39:52 +0700
Subject: [PATCH 06/16] add web
---
client/.dockerignore | 14 +
client/.gitignore | 4 +
client/Dockerfile.api | 16 +
client/Dockerfile.web | 31 +
client/backend/requirements.txt | 17 +
client/backend/tasks.sh | 3 +-
client/compose.yaml | 21 +
client/pb/CHANGELOG.md | 936 -----
client/pb/LICENSE.md | 17 -
client/pb/pb_hooks/main.pb.js | 2 +-
client/web/.env.development | 2 +
client/web/.env.production | 2 +
client/web/.eslintrc.cjs | 13 +
client/web/.gitignore | 24 +
client/web/README.md | 6 +
client/web/components.json | 17 +
client/web/index.html | 13 +
client/web/package.json | 56 +
client/web/pnpm-lock.yaml | 3374 +++++++++++++++++
client/web/postcss.config.js | 6 +
client/web/public/vite.svg | 1 +
client/web/src/App.css | 13 +
client/web/src/App.jsx | 54 +
client/web/src/assets/react.svg | 1 +
client/web/src/components/article-list.jsx | 33 +
client/web/src/components/layout/step.jsx | 21 +
client/web/src/components/screen/articles.jsx | 74 +
client/web/src/components/screen/insights.jsx | 160 +
client/web/src/components/screen/login.jsx | 82 +
client/web/src/components/screen/report.jsx | 98 +
client/web/src/components/screen/start.jsx | 58 +
client/web/src/components/screen/steps.jsx | 105 +
client/web/src/components/ui/accordion.jsx | 41 +
client/web/src/components/ui/banner.jsx | 9 +
.../web/src/components/ui/button-loading.jsx | 11 +
client/web/src/components/ui/button.jsx | 47 +
client/web/src/components/ui/form.jsx | 133 +
client/web/src/components/ui/input.jsx | 19 +
client/web/src/components/ui/label.jsx | 16 +
client/web/src/components/ui/textarea.jsx | 18 +
client/web/src/components/ui/toast.jsx | 82 +
client/web/src/components/ui/toaster.jsx | 33 +
client/web/src/components/ui/use-toast.js | 154 +
client/web/src/index.css | 82 +
client/web/src/lib/utils.js | 18 +
client/web/src/main.jsx | 10 +
client/web/src/store.js | 273 ++
client/web/tailwind.config.js | 77 +
client/web/tsconfig.json | 8 +
client/web/vite.config.js | 15 +
50 files changed, 5365 insertions(+), 955 deletions(-)
create mode 100644 client/.dockerignore
create mode 100644 client/.gitignore
create mode 100644 client/Dockerfile.api
create mode 100644 client/Dockerfile.web
create mode 100644 client/backend/requirements.txt
create mode 100644 client/compose.yaml
delete mode 100644 client/pb/CHANGELOG.md
delete mode 100644 client/pb/LICENSE.md
create mode 100644 client/web/.env.development
create mode 100644 client/web/.env.production
create mode 100644 client/web/.eslintrc.cjs
create mode 100644 client/web/.gitignore
create mode 100644 client/web/README.md
create mode 100644 client/web/components.json
create mode 100644 client/web/index.html
create mode 100644 client/web/package.json
create mode 100644 client/web/pnpm-lock.yaml
create mode 100644 client/web/postcss.config.js
create mode 100644 client/web/public/vite.svg
create mode 100644 client/web/src/App.css
create mode 100644 client/web/src/App.jsx
create mode 100644 client/web/src/assets/react.svg
create mode 100644 client/web/src/components/article-list.jsx
create mode 100644 client/web/src/components/layout/step.jsx
create mode 100644 client/web/src/components/screen/articles.jsx
create mode 100644 client/web/src/components/screen/insights.jsx
create mode 100644 client/web/src/components/screen/login.jsx
create mode 100644 client/web/src/components/screen/report.jsx
create mode 100644 client/web/src/components/screen/start.jsx
create mode 100644 client/web/src/components/screen/steps.jsx
create mode 100644 client/web/src/components/ui/accordion.jsx
create mode 100644 client/web/src/components/ui/banner.jsx
create mode 100644 client/web/src/components/ui/button-loading.jsx
create mode 100644 client/web/src/components/ui/button.jsx
create mode 100644 client/web/src/components/ui/form.jsx
create mode 100644 client/web/src/components/ui/input.jsx
create mode 100644 client/web/src/components/ui/label.jsx
create mode 100644 client/web/src/components/ui/textarea.jsx
create mode 100644 client/web/src/components/ui/toast.jsx
create mode 100644 client/web/src/components/ui/toaster.jsx
create mode 100644 client/web/src/components/ui/use-toast.js
create mode 100644 client/web/src/index.css
create mode 100644 client/web/src/lib/utils.js
create mode 100644 client/web/src/main.jsx
create mode 100644 client/web/src/store.js
create mode 100644 client/web/tailwind.config.js
create mode 100644 client/web/tsconfig.json
create mode 100644 client/web/vite.config.js
diff --git a/client/.dockerignore b/client/.dockerignore
new file mode 100644
index 0000000..4d15359
--- /dev/null
+++ b/client/.dockerignore
@@ -0,0 +1,14 @@
+.git
+.vscode
+.dockerignore
+.gitignore
+.env
+config
+build
+web/dist
+web/node_modules
+docker-compose.yaml
+Dockerfile
+README.md
+backend/__pycache__
+backend/AWtest
\ No newline at end of file
diff --git a/client/.gitignore b/client/.gitignore
new file mode 100644
index 0000000..783ac3b
--- /dev/null
+++ b/client/.gitignore
@@ -0,0 +1,4 @@
+.env
+.venv/
+pb/pb_data/
+backend/AWtest/
\ No newline at end of file
diff --git a/client/Dockerfile.api b/client/Dockerfile.api
new file mode 100644
index 0000000..6e10a9b
--- /dev/null
+++ b/client/Dockerfile.api
@@ -0,0 +1,16 @@
+FROM python:3.10-slim
+
+RUN apt-get update && \
+ apt-get install -yq tzdata && \
+ ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
+ dpkg-reconfigure -f noninteractive tzdata
+
+WORKDIR /app
+
+COPY backend/requirements.txt requirements.txt
+RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
+
+COPY backend ./
+
+EXPOSE 7777
+CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7777"]
\ No newline at end of file
diff --git a/client/Dockerfile.web b/client/Dockerfile.web
new file mode 100644
index 0000000..d4ef67d
--- /dev/null
+++ b/client/Dockerfile.web
@@ -0,0 +1,31 @@
+FROM node:20-slim as builder
+
+WORKDIR /app
+
+COPY web ./
+RUN npm install -g pnpm
+RUN pnpm install
+RUN pnpm build
+
+
+FROM alpine:latest
+
+ARG PB_VERSION=0.21.1
+
+RUN apk add --no-cache unzip ca-certificates tzdata
+
+# download and unzip PocketBase
+ADD https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_linux_amd64.zip /tmp/pb.zip
+RUN unzip /tmp/pb.zip -d /pb/
+
+RUN mkdir -p /pb
+
+COPY ./pb/pb_migrations /pb/pb_migrations
+COPY ./pb/pb_hooks /pb/pb_hooks
+COPY --from=builder /app/dist /pb/pb_public
+
+WORKDIR /pb
+
+EXPOSE 8090
+
+CMD ["/pb/pocketbase", "serve", "--http=0.0.0.0:8090"]
diff --git a/client/backend/requirements.txt b/client/backend/requirements.txt
new file mode 100644
index 0000000..e2148b6
--- /dev/null
+++ b/client/backend/requirements.txt
@@ -0,0 +1,17 @@
+fastapi
+pydantic
+uvicorn
+dashscope #optional(使用阿里灵积时安装)
+volcengine #optional(使用火山翻译时安装)
+python-docx
+BCEmbedding==0.1.3
+langchain==0.1.0
+langchain-community==0.0.9
+langchain-core==0.1.7
+langsmith==0.0.77
+# faiss-gpu for gpu environment
+faiss-cpu # for cpu-only environment
+pocketbase==0.10.0
+gne
+selenium
+chardet
\ No newline at end of file
diff --git a/client/backend/tasks.sh b/client/backend/tasks.sh
index 8cbccf6..f3ea41d 100755
--- a/client/backend/tasks.sh
+++ b/client/backend/tasks.sh
@@ -1,3 +1,4 @@
+set -o allexport
source ../.env
-
+set +o allexport
python background_task.py
\ No newline at end of file
diff --git a/client/compose.yaml b/client/compose.yaml
new file mode 100644
index 0000000..88c0a7a
--- /dev/null
+++ b/client/compose.yaml
@@ -0,0 +1,21 @@
+services:
+ web:
+ build:
+ dockerfile: Dockerfile.web
+ ports:
+ - 8090:8090
+ # env_file:
+ # - .env
+ volumes:
+ - ./pb/pb_data:/pb/pb_data
+ # - ./${PROJECT_DIR}:/pb/${PROJECT_DIR}
+ api:
+ build:
+ dockerfile: Dockerfile.api
+ env_file:
+ - .env
+ ports:
+ - 7777:7777
+ volumes:
+ #- ./${PROJECT_DIR}:/app/${PROJECT_DIR}
+ - ${EMBEDDING_MODEL_PATH}:${EMBEDDING_MODEL_PATH}
diff --git a/client/pb/CHANGELOG.md b/client/pb/CHANGELOG.md
deleted file mode 100644
index 2e6ee75..0000000
--- a/client/pb/CHANGELOG.md
+++ /dev/null
@@ -1,936 +0,0 @@
-## v0.22.3
-
-- Fixed the z-index of the current admin dropdown on Safari ([#4492](https://github.com/pocketbase/pocketbase/issues/4492)).
-
-- Fixed `OnAfterApiError` debug log `nil` error reference ([#4498](https://github.com/pocketbase/pocketbase/issues/4498)).
-
-- Added the field name as part of the `@request.data.someRelField.*` join to handle the case when a collection has 2 or more relation fields pointing to the same place ([#4500](https://github.com/pocketbase/pocketbase/issues/4500)).
-
-- Updated Go deps and bumped the min Go version in the GitHub release action to Go 1.22.1 since it comes with [some security fixes](https://github.com/golang/go/issues?q=milestone%3AGo1.22.1).
-
-
-## v0.22.2
-
-- Fixed a small regression introduced with v0.22.0 that was causing some missing unknown fields to always return an error instead of applying the specific `nullifyMisingField` resolver option to the query.
-
-
-## v0.22.1
-
-- Fixed Admin UI record and collection panels not reinitializing properly on browser back/forward navigation ([#4462](https://github.com/pocketbase/pocketbase/issues/4462)).
-
-- Initialize `RecordAuthWithOAuth2Event.IsNewRecord` for the `OnRecordBeforeAuthWithOAuth2Request` hook ([#4437](https://github.com/pocketbase/pocketbase/discussions/4437)).
-
-- Added error checks to the autogenerated Go migrations ([#4448](https://github.com/pocketbase/pocketbase/issues/4448)).
-
-
-## v0.22.0
-
-- Added Planning Center OAuth2 provider ([#4393](https://github.com/pocketbase/pocketbase/pull/4393); thanks @alxjsn).
-
-- Admin UI improvements:
- - Autosync collection changes across multiple open browser tabs.
- - Fixed vertical image popup preview scrolling.
- - Added options to export a subset of collections.
- - Added option to import a subset of collections without deleting the others ([#3403](https://github.com/pocketbase/pocketbase/issues/3403)).
-
-- Added support for back/indirect relation `filter`/`sort` (single and multiple).
- The syntax to reference back relation fields is `yourCollection_via_yourRelField.*`.
- ⚠️ To avoid excessive joins, the nested relations resolver is now limited to max 6 level depth (the same as `expand`).
- _Note that in the future there will be also more advanced and granular options to specify a subset of the fields that are filterable/sortable._
-
-- Added support for multiple back/indirect relation `expand` and updated the keys to use the `_via_` reference syntax (`yourCollection_via_yourRelField`).
- _To minimize the breaking changes, the old parenthesis reference syntax (`yourCollection(yourRelField)`) will still continue to work but it is soft-deprecated and there will be a console log reminding you to change it to the new one._
-
-- ⚠️ Collections and fields are no longer allowed to have `_via_` in their name to avoid collisions with the back/indirect relation reference syntax.
-
-- Added `jsvm.Config.OnInit` optional config function to allow registering custom Go bindings to the JSVM.
-
-- Added `@request.context` rule field that can be used to apply a different set of constraints based on the API rule execution context.
- For example, to disallow user creation by an OAuth2 auth, you could set for the users Create API rule `@request.context != "oauth2"`.
- The currently supported `@request.context` values are:
- ```
- default
- realtime
- protectedFile
- oauth2
- ```
-
-- Adjusted the `cron.Start()` to start the ticker at the `00` second of the cron interval ([#4394](https://github.com/pocketbase/pocketbase/discussions/4394)).
- _Note that the cron format has only minute granularity and there is still no guarantee that the scheduled job will be always executed at the `00` second._
-
-- Fixed auto backups cron not reloading properly after app settings change ([#4431](https://github.com/pocketbase/pocketbase/discussions/4431)).
-
-- Upgraded to `aws-sdk-go-v2` and added special handling for GCS to workaround the previous [GCS headers signature issue](https://github.com/pocketbase/pocketbase/issues/2231) that we had with v2.
- _This should also fix the SVG/JSON zero response when using Cloudflare R2 ([#4287](https://github.com/pocketbase/pocketbase/issues/4287#issuecomment-1925168142), [#2068](https://github.com/pocketbase/pocketbase/discussions/2068), [#2952](https://github.com/pocketbase/pocketbase/discussions/2952))._
- _⚠️ If you are using S3 for uploaded files or backups, please verify that you have a green check in the Admin UI for your S3 configuration (I've tested the new version with GCS, MinIO, Cloudflare R2 and Wasabi)._
-
-- Added `:each` modifier support for `file` and `relation` type fields (_previously it was supported only for `select` type fields_).
-
-- Other minor improvements (updated the `ghupdate` plugin to use the configured executable name when printing to the console, fixed the error reporting of `admin update/delete` commands, etc.).
-
-
-## v0.21.3
-
-- Ignore the JS required validations for disabled OIDC providers ([#4322](https://github.com/pocketbase/pocketbase/issues/4322)).
-
-- Allow `HEAD` requests to the `/api/health` endpoint ([#4310](https://github.com/pocketbase/pocketbase/issues/4310)).
-
-- Fixed the `editor` field value when visualized inside the View collection preview panel.
-
-- Manually clear all TinyMCE events on editor removal (_workaround for [tinymce#9377](https://github.com/tinymce/tinymce/issues/9377)_).
-
-
-## v0.21.2
-
-- Fixed `@request.auth.*` initialization side-effect which caused the current authenticated user email to not being returned in the user auth response ([#2173](https://github.com/pocketbase/pocketbase/issues/2173#issuecomment-1932332038)).
- _The current authenticated user email should be accessible always no matter of the `emailVisibility` state._
-
-- Fixed `RecordUpsert.RemoveFiles` godoc example.
-
-- Bumped to `NumCPU()+2` the `thumbGenSem` limit as some users reported that it was too restrictive.
-
-
-## v0.21.1
-
-- Small fix for the Admin UI related to the _Settings > Sync_ menu not being visible even when the "Hide controls" toggle is off.
-
-
-## v0.21.0
-
-- Added Bitbucket OAuth2 provider ([#3948](https://github.com/pocketbase/pocketbase/pull/3948); thanks @aabajyan).
-
-- Mark user as verified on confirm password reset ([#4066](https://github.com/pocketbase/pocketbase/issues/4066)).
- _If the user email has changed after issuing the reset token (eg. updated by an admin), then the `verified` user state remains unchanged._
-
-- Added support for loading a serialized json payload for `multipart/form-data` requests using the special `@jsonPayload` key.
- _This is intended to be used primarily by the SDKs to resolve [js-sdk#274](https://github.com/pocketbase/js-sdk/issues/274)._
-
-- Added graceful OAuth2 redirect error handling ([#4177](https://github.com/pocketbase/pocketbase/issues/4177)).
- _Previously on redirect error we were returning directly a standard json error response. Now on redirect error we'll redirect to a generic OAuth2 failure screen (similar to the success one) and will attempt to auto close the OAuth2 popup._
- _The SDKs are also updated to handle the OAuth2 redirect error and it will be returned as Promise rejection of the `authWithOAuth2()` call._
-
-- Exposed `$apis.gzip()` and `$apis.bodyLimit(bytes)` middlewares to the JSVM.
-
-- Added `TestMailer.SentMessages` field that holds all sent test app emails until cleanup.
-
-- Optimized the cascade delete of records with multiple `relation` fields.
-
-- Updated the `serve` and `admin` commands error reporting.
-
-- Minor Admin UI improvements (reduced the min table row height, added option to duplicate fields, added new TinyMCE codesample plugin languages, hide the collection sync settings when the `Settings.Meta.HideControls` is enabled, etc.)
-
-
-## v0.20.7
-
-- Fixed the Admin UI auto indexes update when renaming fields with a common prefix ([#4160](https://github.com/pocketbase/pocketbase/issues/4160)).
-
-
-## v0.20.6
-
-- Fixed JSVM types generation for functions with omitted arg types ([#4145](https://github.com/pocketbase/pocketbase/issues/4145)).
-
-- Updated Go deps.
-
-
-## v0.20.5
-
-- Minor CSS fix for the Admin UI to prevent the searchbar within a popup from expanding too much and pushing the controls out of the visible area ([#4079](https://github.com/pocketbase/pocketbase/issues/4079#issuecomment-1876994116)).
-
-
-## v0.20.4
-
-- Small fix for a regression introduced with the recent `json` field changes that was causing View collection column expressions recognized as `json` to fail to resolve ([#4072](https://github.com/pocketbase/pocketbase/issues/4072)).
-
-
-## v0.20.3
-
-- Fixed the `json` field query comparisons to work correctly with plain JSON values like `null`, `bool` `number`, etc. ([#4068](https://github.com/pocketbase/pocketbase/issues/4068)).
- Since there are plans in the future to allow custom SQLite builds and also in some situations it may be useful to be able to distinguish `NULL` from `''`,
- for the `json` fields (and for any other future non-standard field) we no longer apply `COALESCE` by default, aka.:
- ```
- Dataset:
- 1) data: json(null)
- 2) data: json('')
-
- For the filter "data = null" only 1) will resolve to TRUE.
- For the filter "data = ''" only 2) will resolve to TRUE.
- ```
-
-- Minor Go tests improvements
- - Sorted the record cascade delete references to ensure that the delete operation will preserve the order of the fired events when running the tests.
- - Marked some of the tests as safe for parallel execution to speed up a little the GitHub action build times.
-
-
-## v0.20.2
-
-- Added `sleep(milliseconds)` JSVM binding.
- _It works the same way as Go `time.Sleep()`, aka. it pauses the goroutine where the JSVM code is running._
-
-- Fixed multi-line text paste in the Admin UI search bar ([#4022](https://github.com/pocketbase/pocketbase/discussions/4022)).
-
-- Fixed the monospace font loading in the Admin UI.
-
-- Fixed various reported docs and code comment typos.
-
-
-## v0.20.1
-
-- Added `--dev` flag and its accompanying `app.IsDev()` method (_in place of the previously removed `--debug`_) to assist during development ([#3918](https://github.com/pocketbase/pocketbase/discussions/3918)).
- The `--dev` flag prints in the console "everything" and more specifically:
- - the data DB SQL statements
- - all `app.Logger().*` logs (debug, info, warning, error, etc.), no matter of the logs persistence settings in the Admin UI
-
-- Minor Admin UI fixes:
- - Fixed the log `error` label text wrapping.
- - Added the log `referer` (_when it is from a different source_) and `details` labels in the logs listing.
- - Removed the blank current time entry from the logs chart because it was causing confusion when used with custom time ranges.
- - Updated the SQL syntax highlighter and keywords autocompletion in the Admin UI to recognize `CAST(x as bool)` expressions.
-
-- Replaced the default API tests timeout with a new `ApiScenario.Timeout` option ([#3930](https://github.com/pocketbase/pocketbase/issues/3930)).
- A negative or zero value means no tests timeout.
- If a single API test takes more than 3s to complete it will have a log message visible when the test fails or when `go test -v` flag is used.
-
-- Added timestamp at the beginning of the generated JSVM types file to avoid creating it everytime with the app startup.
-
-
-## v0.20.0
-
-- Added `expand`, `filter`, `fields`, custom query and headers parameters support for the realtime subscriptions.
- _Requires JS SDK v0.20.0+ or Dart SDK v0.17.0+._
-
- ```js
- // JS SDK v0.20.0
- pb.collection("example").subscribe("*", (e) => {
- ...
- }, {
- expand: "someRelField",
- filter: "status = 'active'",
- fields: "id,expand.someRelField.*:excerpt(100)",
- })
- ```
-
- ```dart
- // Dart SDK v0.17.0
- pb.collection("example").subscribe("*", (e) {
- ...
- },
- expand: "someRelField",
- filter: "status = 'active'",
- fields: "id,expand.someRelField.*:excerpt(100)",
- )
- ```
-
-- Generalized the logs to allow any kind of application logs, not just requests.
-
- The new `app.Logger()` implements the standard [`log/slog` interfaces](https://pkg.go.dev/log/slog) available with Go 1.21.
- ```
- // Go: https://pocketbase.io/docs/go-logging/
- app.Logger().Info("Example message", "total", 123, "details", "lorem ipsum...")
-
- // JS: https://pocketbase.io/docs/js-logging/
- $app.logger().info("Example message", "total", 123, "details", "lorem ipsum...")
- ```
-
- For better performance and to minimize blocking on hot paths, logs are currently written with
- debounce and on batches:
- - 3 seconds after the last debounced log write
- - when the batch threshold is reached (currently 200)
- - right before app termination to attempt saving everything from the existing logs queue
-
- Some notable log related changes:
-
- - ⚠️ Bumped the minimum required Go version to 1.21.
-
- - ⚠️ Removed `_requests` table in favor of the generalized `_logs`.
- _Note that existing logs will be deleted!_
-
- - ⚠️ Renamed the following `Dao` log methods:
- ```go
- Dao.RequestQuery(...) -> Dao.LogQuery(...)
- Dao.FindRequestById(...) -> Dao.FindLogById(...)
- Dao.RequestsStats(...) -> Dao.LogsStats(...)
- Dao.DeleteOldRequests(...) -> Dao.DeleteOldLogs(...)
- Dao.SaveRequest(...) -> Dao.SaveLog(...)
- ```
- - ⚠️ Removed `app.IsDebug()` and the `--debug` flag.
- This was done to avoid the confusion with the new logger and its debug severity level.
- If you want to store debug logs you can set `-4` as min log level from the Admin UI.
-
- - Refactored Admin UI Logs:
- - Added new logs table listing.
- - Added log settings option to toggle the IP logging for the activity logger.
- - Added log settings option to specify a minimum log level.
- - Added controls to export individual or bulk selected logs as json.
- - Other minor improvements and fixes.
-
-- Added new `filesystem/System.Copy(src, dest)` method to copy existing files from one location to another.
- _This is usually useful when duplicating records with `file` field(s) programmatically._
-
-- Added `filesystem.NewFileFromUrl(ctx, url)` helper method to construct a `*filesystem.BytesReader` file from the specified url.
-
-- OAuth2 related additions:
-
- - Added new `PKCE()` and `SetPKCE(enable)` OAuth2 methods to indicate whether the PKCE flow is supported or not.
- _The PKCE value is currently configurable from the UI only for the OIDC providers._
- _This was added to accommodate OIDC providers that may throw an error if unsupported PKCE params are submitted with the auth request (eg. LinkedIn; see [#3799](https://github.com/pocketbase/pocketbase/discussions/3799#discussioncomment-7640312))._
-
- - Added new `displayName` field for each `listAuthMethods()` OAuth2 provider item.
- _The value of the `displayName` property is currently configurable from the UI only for the OIDC providers._
-
- - Added `expiry` field to the OAuth2 user response containing the _optional_ expiration time of the OAuth2 access token ([#3617](https://github.com/pocketbase/pocketbase/discussions/3617)).
-
- - Allow a single OAuth2 user to be used for authentication in multiple auth collection.
- _⚠️ Because now you can have more than one external provider with `collectionId-provider-providerId` pair, `Dao.FindExternalAuthByProvider(provider, providerId)` method was removed in favour of the more generic `Dao.FindFirstExternalAuthByExpr(expr)`._
-
-- Added `onlyVerified` auth collection option to globally disallow authentication requests for unverified users.
-
-- Added support for single line comments (ex. `// your comment`) in the API rules and filter expressions.
-
-- Added support for specifying a collection alias in `@collection.someCollection:alias.*`.
-
-- Soft-deprecated and renamed `app.Cache()` with `app.Store()`.
-
-- Minor JSVM updates and fixes:
-
- - Updated `$security.parseUnverifiedJWT(token)` and `$security.parseJWT(token, key)` to return the token payload result as plain object.
-
- - Added `$apis.requireGuestOnly()` middleware JSVM binding ([#3896](https://github.com/pocketbase/pocketbase/issues/3896)).
-
-- Use `IS NOT` instead of `!=` as not-equal SQL query operator to handle the cases when comparing with nullable columns or expressions (eg. `json_extract` over `json` field).
- _Based on my local dataset I wasn't able to find a significant difference in the performance between the 2 operators, but if you stumble on a query that you think may be affected negatively by this, please report it and I'll test it further._
-
-- Added `MaxSize` `json` field option to prevent storing large json data in the db ([#3790](https://github.com/pocketbase/pocketbase/issues/3790)).
- _Existing `json` fields are updated with a system migration to have a ~2MB size limit (it can be adjusted from the Admin UI)._
-
-- Fixed negative string number normalization support for the `json` field type.
-
-- Trigger the `app.OnTerminate()` hook on `app.Restart()` call.
- _A new bool `IsRestart` field was also added to the `core.TerminateEvent` event._
-
-- Fixed graceful shutdown handling and speed up a little the app termination time.
-
-- Limit the concurrent thumbs generation to avoid high CPU and memory usage in spiky scenarios ([#3794](https://github.com/pocketbase/pocketbase/pull/3794); thanks @t-muehlberger).
- _Currently the max concurrent thumbs generation processes are limited to "total of logical process CPUs + 1"._
- _This is arbitrary chosen and may change in the future depending on the users feedback and usage patterns._
- _If you are experiencing OOM errors during large image thumb generations, especially in container environment, you can try defining the `GOMEMLIMIT=500MiB` env variable before starting the executable._
-
-- Slightly speed up (~10%) the thumbs generation by changing from cubic (`CatmullRom`) to bilinear (`Linear`) resampling filter (_the quality difference is very little_).
-
-- Added a default red colored Stderr output in case of a console command error.
- _You can now also silence individually custom commands errors using the `cobra.Command.SilenceErrors` field._
-
-- Fixed links formatting in the autogenerated html->text mail body.
-
-- Removed incorrectly imported empty `local('')` font-face declarations.
-
-
-## v0.19.4
-
-- Fixed TinyMCE source code viewer textarea styles ([#3715](https://github.com/pocketbase/pocketbase/issues/3715)).
-
-- Fixed `text` field min/max validators to properly count multi-byte characters ([#3735](https://github.com/pocketbase/pocketbase/issues/3735)).
-
-- Allowed hyphens in `username` ([#3697](https://github.com/pocketbase/pocketbase/issues/3697)).
- _More control over the system fields settings will be available in the future._
-
-- Updated the JSVM generated types to use directly the value type instead of `* | undefined` union in functions/methods return declarations.
-
-
-## v0.19.3
-
-- Added the release notes to the console output of `./pocketbase update` ([#3685](https://github.com/pocketbase/pocketbase/discussions/3685)).
-
-- Added missing documentation for the JSVM `$mails.*` bindings.
-
-- Relaxed the OAuth2 redirect url validation to allow any string value ([#3689](https://github.com/pocketbase/pocketbase/pull/3689); thanks @sergeypdev).
- _Note that the redirect url format is still bound to the accepted values by the specific OAuth2 provider._
-
-
-## v0.19.2
-
-- Updated the JSVM generated types ([#3627](https://github.com/pocketbase/pocketbase/issues/3627), [#3662](https://github.com/pocketbase/pocketbase/issues/3662)).
-
-
-## v0.19.1
-
-- Fixed `tokenizer.Scan()/ScanAll()` to ignore the separators from the default trim cutset.
- An option to return also the empty found tokens was also added via `Tokenizer.KeepEmptyTokens(true)`.
- _This should fix the parsing of whitespace characters around view query column names when no quotes are used ([#3616](https://github.com/pocketbase/pocketbase/discussions/3616#discussioncomment-7398564))._
-
-- Fixed the `:excerpt(max, withEllipsis?)` `fields` query param modifier to properly add space to the generated text fragment after block tags.
-
-
-## v0.19.0
-
-- Added Patreon OAuth2 provider ([#3323](https://github.com/pocketbase/pocketbase/pull/3323); thanks @ghostdevv).
-
-- Added mailcow OAuth2 provider ([#3364](https://github.com/pocketbase/pocketbase/pull/3364); thanks @thisni1s).
-
-- Added support for `:excerpt(max, withEllipsis?)` `fields` modifier that will return a short plain text version of any string value (html tags are stripped).
- This could be used to minimize the downloaded json data when listing records with large `editor` html values.
- ```js
- await pb.collection("example").getList(1, 20, {
- "fields": "*,description:excerpt(100)"
- })
- ```
-
-- Several Admin UI improvements:
- - Count the total records separately to speed up the query execution for large datasets ([#3344](https://github.com/pocketbase/pocketbase/issues/3344)).
- - Enclosed the listing scrolling area within the table so that the horizontal scrollbar and table header are always reachable ([#2505](https://github.com/pocketbase/pocketbase/issues/2505)).
- - Allowed opening the record preview/update form via direct URL ([#2682](https://github.com/pocketbase/pocketbase/discussions/2682)).
- - Reintroduced the local `date` field tooltip on hover.
- - Speed up the listing loading times for records with large `editor` field values by initially fetching only a partial of the records data (the complete record data is loaded on record preview/update).
- - Added "Media library" (collection images picker) support for the TinyMCE `editor` field.
- - Added support to "pin" collections in the sidebar.
- - Added support to manually resize the collections sidebar.
- - More clear "Nonempty" field label style.
- - Removed the legacy `.woff` and `.ttf` fonts and keep only `.woff2`.
-
-- Removed the explicit `Content-Type` charset from the realtime response due to compatibility issues with IIS ([#3461](https://github.com/pocketbase/pocketbase/issues/3461)).
- _The `Connection:keep-alive` realtime response header was also removed as it is not really used with HTTP2 anyway._
-
-- Added new JSVM bindings:
- - `new Cookie({ ... })` constructor for creating `*http.Cookie` equivalent value.
- - `new SubscriptionMessage({ ... })` constructor for creating a custom realtime subscription payload.
- - Soft-deprecated `$os.exec()` in favour of `$os.cmd()` to make it more clear that the call only prepares the command and doesn't execute it.
-
-- ⚠️ Bumped the min required Go version to 1.19.
-
-
-## v0.18.10
-
-- Added global `raw` template function to allow outputting raw/verbatim HTML content in the JSVM templates ([#3476](https://github.com/pocketbase/pocketbase/discussions/3476)).
- ```
- {{.description|raw}}
- ```
-
-- Trimmed view query semicolon and allowed single quotes for column aliases ([#3450](https://github.com/pocketbase/pocketbase/issues/3450#issuecomment-1748044641)).
- _Single quotes are usually [not a valid identifier quote characters](https://www.sqlite.org/lang_keywords.html), but for resilience and compatibility reasons SQLite allows them in some contexts where only an identifier is expected._
-
-- Bumped the GitHub action to use [min Go 1.21.2](https://github.com/golang/go/issues?q=milestone%3AGo1.21.2) (_the fixed issues are not critical as they are mostly related to the compiler/build tools_).
-
-
-## v0.18.9
-
-- Fixed empty thumbs directories not getting deleted on Windows after deleting a record img file ([#3382](https://github.com/pocketbase/pocketbase/issues/3382)).
-
-- Updated the generated JSVM typings to silent the TS warnings when trying to access a field/method in a Go->TS interface.
-
-
-## v0.18.8
-
-- Minor fix for the View collections API Preview and Admin UI listings incorrectly showing the `created` and `updated` fields as `N/A` when the view query doesn't have them.
-
-
-## v0.18.7
-
-- Fixed JS error in the Admin UI when listing records with invalid `relation` field value ([#3372](https://github.com/pocketbase/pocketbase/issues/3372)).
- _This could happen usually only during custom SQL import scripts or when directly modifying the record field value without data validations._
-
-- Updated Go deps and the generated JSVM types.
-
-
-## v0.18.6
-
-- Return the response headers and cookies in the `$http.send()` result ([#3310](https://github.com/pocketbase/pocketbase/discussions/3310)).
-
-- Added more descriptive internal error message for missing user/admin email on password reset requests.
-
-- Updated Go deps.
-
-
-## v0.18.5
-
-- Fixed minor Admin UI JS error in the auth collection options panel introduced with the change from v0.18.4.
-
-
-## v0.18.4
-
-- Added escape character (`\`) support in the Admin UI to allow using `select` field values with comma ([#2197](https://github.com/pocketbase/pocketbase/discussions/2197)).
-
-
-## v0.18.3
-
-- Exposed a global JSVM `readerToString(reader)` helper function to allow reading Go `io.Reader` values ([#3273](https://github.com/pocketbase/pocketbase/discussions/3273)).
-
-- Bumped the GitHub action to use [min Go 1.21.1](https://github.com/golang/go/issues?q=milestone%3AGo1.21.1+label%3ACherryPickApproved) for the prebuilt executable since it contains some minor `html/template` and `net/http` security fixes.
-
-
-## v0.18.2
-
-- Prevent breaking the record form in the Admin UI in case the browser's localStorage quota has been exceeded when uploading or storing large `editor` values ([#3265](https://github.com/pocketbase/pocketbase/issues/3265)).
-
-- Updated docs and missing JSVM typings.
-
-- Exposed additional crypto primitives under the `$security.*` JSVM namespace ([#3273](https://github.com/pocketbase/pocketbase/discussions/3273)):
- ```js
- // HMAC with SHA256
- $security.hs256("hello", "secret")
-
- // HMAC with SHA512
- $security.hs512("hello", "secret")
-
- // compare 2 strings with a constant time
- $security.equal(hash1, hash2)
- ```
-
-
-## v0.18.1
-
-- Excluded the local temp dir from the backups ([#3261](https://github.com/pocketbase/pocketbase/issues/3261)).
-
-
-## v0.18.0
-
-- Simplified the `serve` command to accept domain name(s) as argument to reduce any additional manual hosts setup that sometimes previously was needed when deploying on production ([#3190](https://github.com/pocketbase/pocketbase/discussions/3190)).
- ```sh
- ./pocketbase serve yourdomain.com
- ```
-
-- Added `fields` wildcard (`*`) support.
-
-- Added option to upload a backup file from the Admin UI ([#2599](https://github.com/pocketbase/pocketbase/issues/2599)).
-
-- Registered a custom Deflate compressor to speedup (_nearly 2-3x_) the backups generation for the sake of a small zip size increase.
- _Based on several local tests, `pb_data` of ~500MB (from which ~350MB+ are several hundred small files) results in a ~280MB zip generated for ~11s (previously it resulted in ~250MB zip but for ~35s)._
-
-- Added the application name as part of the autogenerated backup name for easier identification ([#3066](https://github.com/pocketbase/pocketbase/issues/3066)).
-
-- Added new `SmtpConfig.LocalName` option to specify a custom domain name (or IP address) for the initial EHLO/HELO exchange ([#3097](https://github.com/pocketbase/pocketbase/discussions/3097)).
- _This is usually required for verification purposes only by some SMTP providers, such as on-premise [Gmail SMTP-relay](https://support.google.com/a/answer/2956491)._
-
-- Added `NoDecimal` `number` field option.
-
-- `editor` field improvements:
- - Added new "Strip urls domain" option to allow controlling the default TinyMCE urls behavior (_default to `false` for new content_).
- - Normalized pasted text while still preserving links, lists, tables, etc. formatting ([#3257](https://github.com/pocketbase/pocketbase/issues/3257)).
-
-- Added option to auto generate admin and auth record passwords from the Admin UI.
-
-- Added JSON validation and syntax highlight for the `json` field in the Admin UI ([#3191](https://github.com/pocketbase/pocketbase/issues/3191)).
-
-- Added datetime filter macros:
- ```
- // all macros are UTC based
- @second - @now second number (0-59)
- @minute - @now minute number (0-59)
- @hour - @now hour number (0-23)
- @weekday - @now weekday number (0-6)
- @day - @now day number
- @month - @now month number
- @year - @now year number
- @todayStart - beginning of the current day as datetime string
- @todayEnd - end of the current day as datetime string
- @monthStart - beginning of the current month as datetime string
- @monthEnd - end of the current month as datetime string
- @yearStart - beginning of the current year as datetime string
- @yearEnd - end of the current year as datetime string
- ```
-
-- Added cron expression macros ([#3132](https://github.com/pocketbase/pocketbase/issues/3132)):
- ```
- @yearly - "0 0 1 1 *"
- @annually - "0 0 1 1 *"
- @monthly - "0 0 1 * *"
- @weekly - "0 0 * * 0"
- @daily - "0 0 * * *"
- @midnight - "0 0 * * *"
- @hourly - "0 * * * *"
- ```
-
-- ⚠️ Added offset argument `Dao.FindRecordsByFilter(collection, filter, sort, limit, offset, [params...])`.
- _If you don't need an offset, you can set it to `0`._
-
-- To minimize the footguns with `Dao.FindFirstRecordByFilter()` and `Dao.FindRecordsByFilter()`, the functions now supports an optional placeholder params argument that is safe to be populated with untrusted user input.
- The placeholders are in the same format as when binding regular SQL parameters.
- ```go
- // unsanitized and untrusted filter variables
- status := "..."
- author := "..."
-
- app.Dao().FindFirstRecordByFilter("articles", "status={:status} && author={:author}", dbx.Params{
- "status": status,
- "author": author,
- })
-
- app.Dao().FindRecordsByFilter("articles", "status={:status} && author={:author}", "-created", 10, 0, dbx.Params{
- "status": status,
- "author": author,
- })
- ```
-
-- Added JSVM `$mails.*` binds for the corresponding Go [mails package](https://pkg.go.dev/github.com/pocketbase/pocketbase/mails) functions.
-
-- Added JSVM helper crypto primitives under the `$security.*` namespace:
- ```js
- $security.md5(text)
- $security.sha256(text)
- $security.sha512(text)
- ```
-
-- ⚠️ Deprecated `RelationOptions.DisplayFields` in favor of the new `SchemaField.Presentable` option to avoid the duplication when a single collection is referenced more than once and/or by multiple other collections.
-
-- ⚠️ Fill the `LastVerificationSentAt` and `LastResetSentAt` fields only after a successfull email send ([#3121](https://github.com/pocketbase/pocketbase/issues/3121)).
-
-- ⚠️ Skip API `fields` json transformations for non 20x responses ([#3176](https://github.com/pocketbase/pocketbase/issues/3176)).
-
-- ⚠️ Changes to `tests.ApiScenario` struct:
-
- - The `ApiScenario.AfterTestFunc` now receive as 3rd argument `*http.Response` pointer instead of `*echo.Echo` as the latter is not really useful in this context.
- ```go
- // old
- AfterTestFunc: func(t *testing.T, app *tests.TestApp, e *echo.Echo)
-
- // new
- AfterTestFunc: func(t *testing.T, app *tests.TestApp, res *http.Response)
- ```
-
- - The `ApiScenario.TestAppFactory` now accept the test instance as argument and no longer expect an error as return result ([#3025](https://github.com/pocketbase/pocketbase/discussions/3025#discussioncomment-6592272)).
- ```go
- // old
- TestAppFactory: func() (*tests.TestApp, error)
-
- // new
- TestAppFactory: func(t *testing.T) *tests.TestApp
- ```
- _Returning a `nil` app instance from the factory results in test failure. You can enforce a custom test failure by calling `t.Fatal(err)` inside the factory._
-
-- Bumped the min required TLS version to 1.2 in order to improve the cert reputation score.
-
-- Reduced the default JSVM prewarmed pool size to 25 to reduce the initial memory consumptions (_you can manually adjust the pool size with `--hooksPool=50` if you need to, but the default should suffice for most cases_).
-
-- Update `gocloud.dev` dependency to v0.34 and explicitly set the new `NoTempDir` fileblob option to prevent the cross-device link error introduced with v0.33.
-
-- Other minor Admin UI and docs improvements.
-
-
-## v0.17.7
-
-- Fixed the autogenerated `down` migrations to properly revert the old collection rules in case a change was made in `up` ([#3192](https://github.com/pocketbase/pocketbase/pull/3192); thanks @impact-merlinmarek).
- _Existing `down` migrations can't be fixed but that should be ok as usually the `down` migrations are rarely used against prod environments since they can cause data loss and, while not ideal, the previous old behavior of always setting the rules to `null/nil` is safer than not updating the rules at all._
-
-- Updated some Go deps.
-
-
-## v0.17.6
-
-- Fixed JSVM `require()` file path error when using Windows-style path delimiters ([#3163](https://github.com/pocketbase/pocketbase/issues/3163#issuecomment-1685034438)).
-
-
-## v0.17.5
-
-- Added quotes around the wrapped view query columns introduced with v0.17.4.
-
-
-## v0.17.4
-
-- Fixed Views record retrieval when numeric id is used ([#3110](https://github.com/pocketbase/pocketbase/issues/3110)).
- _With this fix we also now properly recognize `CAST(... as TEXT)` and `CAST(... as BOOLEAN)` as `text` and `bool` fields._
-
-- Fixed `relation` "Cascade delete" tooltip message ([#3098](https://github.com/pocketbase/pocketbase/issues/3098)).
-
-- Fixed jsvm error message prefix on failed migrations ([#3103](https://github.com/pocketbase/pocketbase/pull/3103); thanks @nzhenev).
-
-- Disabled the initial Admin UI admins counter cache when there are no initial admins to allow detecting externally created accounts (eg. with the `admin` command) ([#3106](https://github.com/pocketbase/pocketbase/issues/3106)).
-
-- Downgraded `google/go-cloud` dependency to v0.32.0 until v0.34.0 is released to prevent the `os.TempDir` `cross-device link` errors as too many users complained about it.
-
-
-## v0.17.3
-
-- Fixed Docker `cross-device link` error when creating `pb_data` backups on a local mounted volume ([#3089](https://github.com/pocketbase/pocketbase/issues/3089)).
-
-- Fixed the error messages for relation to views ([#3090](https://github.com/pocketbase/pocketbase/issues/3090)).
-
-- Always reserve space for the scrollbar to reduce the layout shifts in the Admin UI records listing due to the deprecated `overflow: overlay`.
-
-- Enabled lazy loading for the Admin UI thumb images.
-
-
-## v0.17.2
-
-- Soft-deprecated `$http.send({ data: object, ... })` in favour of `$http.send({ body: rawString, ... })`
- to allow sending non-JSON body with the request ([#3058](https://github.com/pocketbase/pocketbase/discussions/3058)).
- The existing `data` prop will still work, but it is recommended to use `body` instead (_to send JSON you can use `JSON.stringify(...)` as body value_).
-
-- Added `core.RealtimeConnectEvent.IdleTimeout` field to allow specifying a different realtime idle timeout duration per client basis ([#3054](https://github.com/pocketbase/pocketbase/discussions/3054)).
-
-- Fixed `apis.RequestData` deprecation log note ([#3068](https://github.com/pocketbase/pocketbase/pull/3068); thanks @gungjodi).
-
-
-## v0.17.1
-
-- Use relative path when redirecting to the OAuth2 providers page in the Admin UI to support subpath deployments ([#3026](https://github.com/pocketbase/pocketbase/pull/3026); thanks @sonyarianto).
-
-- Manually trigger the `OnBeforeServe` hook for `tests.ApiScenario` ([#3025](https://github.com/pocketbase/pocketbase/discussions/3025)).
-
-- Trigger the JSVM `cronAdd()` handler only on app `serve` to prevent unexpected (and eventually duplicated) cron handler calls when custom console commands are used ([#3024](https://github.com/pocketbase/pocketbase/discussions/3024#discussioncomment-6592703)).
-
-- The `console.log()` messages are now written to the `stdout` instead of `stderr`.
-
-
-## v0.17.0
-
-- New more detailed guides for using PocketBase as framework (both Go and JS).
- _If you find any typos or issues with the docs please report them in https://github.com/pocketbase/site._
-
-- Added new experimental JavaScript app hooks binding via [goja](https://github.com/dop251/goja).
- They are available by default with the prebuilt executable if you create `*.pb.js` file(s) in the `pb_hooks` directory.
- Lower your expectations because the integration comes with some limitations. For more details please check the [Extend with JavaScript](https://pocketbase.io/docs/js-overview/) guide.
- Optionally, you can also enable the JS app hooks as part of a custom Go build for dynamic scripting but you need to register the `jsvm` plugin manually:
- ```go
- jsvm.MustRegister(app core.App, config jsvm.Config{})
- ```
-
-- Added Instagram OAuth2 provider ([#2534](https://github.com/pocketbase/pocketbase/pull/2534); thanks @pnmcosta).
-
-- Added VK OAuth2 provider ([#2533](https://github.com/pocketbase/pocketbase/pull/2533); thanks @imperatrona).
-
-- Added Yandex OAuth2 provider ([#2762](https://github.com/pocketbase/pocketbase/pull/2762); thanks @imperatrona).
-
-- Added new fields to `core.ServeEvent`:
- ```go
- type ServeEvent struct {
- App App
- Router *echo.Echo
- // new fields
- Server *http.Server // allows adjusting the HTTP server config (global timeouts, TLS options, etc.)
- CertManager *autocert.Manager // allows adjusting the autocert options (cache dir, host policy, etc.)
- }
- ```
-
-- Added `record.ExpandedOne(rel)` and `record.ExpandedAll(rel)` helpers to retrieve casted single or multiple expand relations from the already loaded "expand" Record data.
-
-- Added rule and filter record `Dao` helpers:
- ```go
- app.Dao().FindRecordsByFilter("posts", "title ~ 'lorem ipsum' && visible = true", "-created", 10)
- app.Dao().FindFirstRecordByFilter("posts", "slug='test' && active=true")
- app.Dao().CanAccessRecord(record, requestInfo, rule)
- ```
-
-- Added `Dao.WithoutHooks()` helper to create a new `Dao` from the current one but without the create/update/delete hooks.
-
-- Use a default fetch function that will return all relations in case the `fetchFunc` argument of `Dao.ExpandRecord(record, expands, fetchFunc)` and `Dao.ExpandRecords(records, expands, fetchFunc)` is `nil`.
-
-- For convenience it is now possible to call `Dao.RecordQuery(collectionModelOrIdentifier)` with just the collection id or name.
- In case an invalid collection id/name string is passed the query will be resolved with cancelled context error.
-
-- Refactored `apis.ApiError` validation errors serialization to allow `map[string]error` and `map[string]any` when generating the public safe formatted `ApiError.Data`.
-
-- Added support for wrapped API errors (_in case Go 1.20+ is used with multiple wrapped errors, the first `apis.ApiError` takes precedence_).
-
-- Added `?download=1` file query parameter to the file serving endpoint to force the browser to always download the file and not show its preview.
-
-- Added new utility `github.com/pocketbase/pocketbase/tools/template` subpackage to assist with rendering HTML templates using the standard Go `html/template` and `text/template` syntax.
-
-- Added `types.JsonMap.Get(k)` and `types.JsonMap.Set(k, v)` helpers for the cases where the type aliased direct map access is not allowed (eg. in [goja](https://pkg.go.dev/github.com/dop251/goja#hdr-Maps_with_methods)).
-
-- Soft-deprecated `security.NewToken()` in favor of `security.NewJWT()`.
-
-- `Hook.Add()` and `Hook.PreAdd` now returns a unique string identifier that could be used to remove the registered hook handler via `Hook.Remove(handlerId)`.
-
-- Changed the after* hooks to be called right before writing the user response, allowing users to return response errors from the after hooks.
- There is also no longer need for returning explicitly `hook.StopPropagtion` when writing custom response body in a hook because we will skip the finalizer response body write if a response was already "committed".
-
-- ⚠️ Renamed `*Options{}` to `Config{}` for consistency and replaced the unnecessary pointers with their value equivalent to keep the applied configuration defaults isolated within their function calls:
- ```go
- old: pocketbase.NewWithConfig(config *pocketbase.Config) *pocketbase.PocketBase
- new: pocketbase.NewWithConfig(config pocketbase.Config) *pocketbase.PocketBase
-
- old: core.NewBaseApp(config *core.BaseAppConfig) *core.BaseApp
- new: core.NewBaseApp(config core.BaseAppConfig) *core.BaseApp
-
- old: apis.Serve(app core.App, options *apis.ServeOptions) error
- new: apis.Serve(app core.App, config apis.ServeConfig) (*http.Server, error)
-
- old: jsvm.MustRegisterMigrations(app core.App, options *jsvm.MigrationsOptions)
- new: jsvm.MustRegister(app core.App, config jsvm.Config)
-
- old: ghupdate.MustRegister(app core.App, rootCmd *cobra.Command, options *ghupdate.Options)
- new: ghupdate.MustRegister(app core.App, rootCmd *cobra.Command, config ghupdate.Config)
-
- old: migratecmd.MustRegister(app core.App, rootCmd *cobra.Command, options *migratecmd.Options)
- new: migratecmd.MustRegister(app core.App, rootCmd *cobra.Command, config migratecmd.Config)
- ```
-
-- ⚠️ Changed the type of `subscriptions.Message.Data` from `string` to `[]byte` because `Data` usually is a json bytes slice anyway.
-
-- ⚠️ Renamed `models.RequestData` to `models.RequestInfo` and soft-deprecated `apis.RequestData(c)` in favor of `apis.RequestInfo(c)` to avoid the stuttering with the `Data` field.
- _The old `apis.RequestData()` method still works to minimize the breaking changes but it is recommended to replace it with `apis.RequestInfo(c)`._
-
-- ⚠️ Changes to the List/Search APIs
- - Added new query parameter `?skipTotal=1` to skip the `COUNT` query performed with the list/search actions ([#2965](https://github.com/pocketbase/pocketbase/discussions/2965)).
- If `?skipTotal=1` is set, the response fields `totalItems` and `totalPages` will have `-1` value (this is to avoid having different JSON responses and to differentiate from the zero default).
- With the latest JS SDK 0.16+ and Dart SDK v0.11+ versions `skipTotal=1` is set by default for the `getFirstListItem()` and `getFullList()` requests.
-
- - The count and regular select statements also now executes concurrently, meaning that we no longer perform normalization over the `page` parameter and in case the user
- request a page that doesn't exist (eg. `?page=99999999`) we'll return empty `items` array.
-
- - Reverted the default `COUNT` column to `id` as there are some common situations where it can negatively impact the query performance.
- Additionally, from this version we also set `PRAGMA temp_store = MEMORY` so that also helps with the temp B-TREE creation when `id` is used.
- _There are still scenarios where `COUNT` queries with `rowid` executes faster, but the majority of the time when nested relations lookups are used it seems to have the opposite effect (at least based on the benchmarks dataset)._
-
-- ⚠️ Disallowed relations to views **from non-view** collections ([#3000](https://github.com/pocketbase/pocketbase/issues/3000)).
- The change was necessary because I wasn't able to find an efficient way to track view changes and the previous behavior could have too many unexpected side-effects (eg. view with computed ids).
- There is a system migration that will convert the existing view `relation` fields to `json` (multiple) and `text` (single) fields.
- This could be a breaking change if you have `relation` to view and use `expand` or some of the `relation` view fields as part of a collection rule.
-
-- ⚠️ Added an extra `action` argument to the `Dao` hooks to allow skipping the default persist behavior.
- In preparation for the logs generalization, the `Dao.After*Func` methods now also allow returning an error.
-
-- Allowed `0` as `RelationOptions.MinSelect` value to avoid the ambiguity between 0 and non-filled input value ([#2817](https://github.com/pocketbase/pocketbase/discussions/2817)).
-
-- Fixed zero-default value not being used if the field is not explicitly set when manually creating records ([#2992](https://github.com/pocketbase/pocketbase/issues/2992)).
- Additionally, `record.Get(field)` will now always return normalized value (the same as in the json serialization) for consistency and to avoid ambiguities with what is stored in the related DB table.
- The schema fields columns `DEFAULT` definition was also updated for new collections to ensure that `NULL` values can't be accidentally inserted.
-
-- Fixed `migrate down` not returning the correct `lastAppliedMigrations()` when the stored migration applied time is in seconds.
-
-- Fixed realtime delete event to be called after the record was deleted from the DB (_including transactions and cascade delete operations_).
-
-- Other minor fixes and improvements (typos and grammar fixes, updated dependencies, removed unnecessary 404 error check in the Admin UI, etc.).
-
-
-## v0.16.10
-
-- Added multiple valued fields (`relation`, `select`, `file`) normalizations to ensure that the zero-default value of a newly created multiple field is applied for already existing data ([#2930](https://github.com/pocketbase/pocketbase/issues/2930)).
-
-
-## v0.16.9
-
-- Register the `eagerRequestInfoCache` middleware only for the internal `api` group routes to avoid conflicts with custom route handlers ([#2914](https://github.com/pocketbase/pocketbase/issues/2914)).
-
-
-## v0.16.8
-
-- Fixed unique validator detailed error message not being returned when camelCase field name is used ([#2868](https://github.com/pocketbase/pocketbase/issues/2868)).
-
-- Updated the index parser to allow no space between the table name and the columns list ([#2864](https://github.com/pocketbase/pocketbase/discussions/2864#discussioncomment-6373736)).
-
-- Updated go deps.
-
-
-## v0.16.7
-
-- Minor optimization for the list/search queries to use `rowid` with the `COUNT` statement when available.
- _This eliminates the temp B-TREE step when executing the query and for large datasets (eg. 150k) it could have 10x improvement (from ~580ms to ~60ms)._
-
-
-## v0.16.6
-
-- Fixed collection index column sort normalization in the Admin UI ([#2681](https://github.com/pocketbase/pocketbase/pull/2681); thanks @SimonLoir).
-
-- Removed unnecessary admins count in `apis.RequireAdminAuthOnlyIfAny()` middleware ([#2726](https://github.com/pocketbase/pocketbase/pull/2726); thanks @svekko).
-
-- Fixed `multipart/form-data` request bind not populating map array values ([#2763](https://github.com/pocketbase/pocketbase/discussions/2763#discussioncomment-6278902)).
-
-- Upgraded npm and Go dependencies.
-
-
-## v0.16.5
-
-- Fixed the Admin UI serialization of implicit relation display fields ([#2675](https://github.com/pocketbase/pocketbase/issues/2675)).
-
-- Reset the Admin UI sort in case the active sort collection field is renamed or deleted.
-
-
-## v0.16.4
-
-- Fixed the selfupdate command not working on Windows due to missing `.exe` in the extracted binary path ([#2589](https://github.com/pocketbase/pocketbase/discussions/2589)).
- _Note that the command on Windows will work from v0.16.4+ onwards, meaning that you still will have to update manually one more time to v0.16.4._
-
-- Added `int64`, `int32`, `uint`, `uint64` and `uint32` support when scanning `types.DateTime` ([#2602](https://github.com/pocketbase/pocketbase/discussions/2602))
-
-- Updated dependencies.
-
-
-## v0.16.3
-
-- Fixed schema fields sort not working on Safari/Gnome Web ([#2567](https://github.com/pocketbase/pocketbase/issues/2567)).
-
-- Fixed default `PRAGMA`s not being applied for new connections ([#2570](https://github.com/pocketbase/pocketbase/discussions/2570)).
-
-
-## v0.16.2
-
-- Fixed backups archive not excluding the local `backups` directory on Windows ([#2548](https://github.com/pocketbase/pocketbase/discussions/2548#discussioncomment-5979712)).
-
-- Changed file field to not use `dataTransfer.effectAllowed` when dropping files since it is not reliable and consistent across different OS and browsers ([#2541](https://github.com/pocketbase/pocketbase/issues/2541)).
-
-- Auto register the initial generated snapshot migration to prevent incorrectly reapplying the snapshot on Docker restart ([#2551](https://github.com/pocketbase/pocketbase/discussions/2551)).
-
-- Fixed missing view id field error message typo.
-
-
-## v0.16.1
-
-- Fixed backup restore not working in a container environment when `pb_data` is mounted as volume ([#2519](https://github.com/pocketbase/pocketbase/issues/2519)).
-
-- Fixed Dart SDK realtime API preview example ([#2523](https://github.com/pocketbase/pocketbase/pull/2523); thanks @xFrann).
-
-- Fixed typo in the backups create panel ([#2526](https://github.com/pocketbase/pocketbase/pull/2526); thanks @dschissler).
-
-- Removed unnecessary slice length check in `list.ExistInSlice` ([#2527](https://github.com/pocketbase/pocketbase/pull/2527); thanks @KunalSin9h).
-
-- Avoid mutating the cached request data on OAuth2 user create ([#2535](https://github.com/pocketbase/pocketbase/discussions/2535)).
-
-- Fixed Export Collections "Download as JSON" ([#2540](https://github.com/pocketbase/pocketbase/issues/2540)).
-
-- Fixed file field drag and drop not working in Firefox and Safari ([#2541](https://github.com/pocketbase/pocketbase/issues/2541)).
-
-
-## v0.16.0
-
-- Added automated backups (_+ cron rotation_) APIs and UI for the `pb_data` directory.
- The backups can be also initialized programmatically using `app.CreateBackup("backup.zip")`.
- There is also experimental restore method - `app.RestoreBackup("backup.zip")` (_currently works only on UNIX systems as it relies on execve_).
- The backups can be stored locally or in external S3 storage (_it has its own configuration, separate from the file uploads storage filesystem_).
-
-- Added option to limit the returned API fields using the `?fields` query parameter.
- The "fields picker" is applied for `SearchResult.Items` and every other JSON response. For example:
- ```js
- // original: {"id": "RECORD_ID", "name": "abc", "description": "...something very big...", "items": ["id1", "id2"], "expand": {"items": [{"id": "id1", "name": "test1"}, {"id": "id2", "name": "test2"}]}}
- // output: {"name": "abc", "expand": {"items": [{"name": "test1"}, {"name": "test2"}]}}
- const result = await pb.collection("example").getOne("RECORD_ID", {
- expand: "items",
- fields: "name,expand.items.name",
- })
- ```
-
-- Added new `./pocketbase update` command to selfupdate the prebuilt executable (with option to generate a backup of your `pb_data`).
-
-- Added new `./pocketbase admin` console command:
- ```sh
- // creates new admin account
- ./pocketbase admin create test@example.com 123456890
-
- // changes the password of an existing admin account
- ./pocketbase admin update test@example.com 0987654321
-
- // deletes single admin account (if exists)
- ./pocketbase admin delete test@example.com
- ```
-
-- Added `apis.Serve(app, options)` helper to allow starting the API server programmatically.
-
-- Updated the schema fields Admin UI for "tidier" fields visualization.
-
-- Updated the logs "real" user IP to check for `Fly-Client-IP` header and changed the `X-Forward-For` header to use the first non-empty leftmost-ish IP as it the closest to the "real IP".
-
-- Added new `tools/archive` helper subpackage for managing archives (_currently works only with zip_).
-
-- Added new `tools/cron` helper subpackage for scheduling task using cron-like syntax (_this eventually may get exported in the future in a separate repo_).
-
-- Added new `Filesystem.List(prefix)` helper to retrieve a flat list with all files under the provided prefix.
-
-- Added new `App.NewBackupsFilesystem()` helper to create a dedicated filesystem abstraction for managing app data backups.
-
-- Added new `App.OnTerminate()` hook (_executed right before app termination, eg. on `SIGTERM` signal_).
-
-- Added `accept` file field attribute with the field MIME types ([#2466](https://github.com/pocketbase/pocketbase/pull/2466); thanks @Nikhil1920).
-
-- Added support for multiple files sort in the Admin UI ([#2445](https://github.com/pocketbase/pocketbase/issues/2445)).
-
-- Added support for multiple relations sort in the Admin UI.
-
-- Added `meta.isNew` to the OAuth2 auth JSON response to indicate a newly OAuth2 created PocketBase user.
diff --git a/client/pb/LICENSE.md b/client/pb/LICENSE.md
deleted file mode 100644
index e3b8465..0000000
--- a/client/pb/LICENSE.md
+++ /dev/null
@@ -1,17 +0,0 @@
-The MIT License (MIT)
-Copyright (c) 2022 - present, Gani Georgiev
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software
-and associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or
-substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/client/pb/pb_hooks/main.pb.js b/client/pb/pb_hooks/main.pb.js
index 7f585e8..44bf76a 100644
--- a/client/pb/pb_hooks/main.pb.js
+++ b/client/pb/pb_hooks/main.pb.js
@@ -43,7 +43,7 @@ routerAdd(
})
)
- $app.dao().db().newQuery("SELECT DISTINCT DATE(created) as created FROM insights").all(result)
+ $app.dao().db().newQuery("SELECT DISTINCT DATE(created, 'localtime') as created FROM insights").all(result)
return c.json(
200,
diff --git a/client/web/.env.development b/client/web/.env.development
new file mode 100644
index 0000000..8a5ae01
--- /dev/null
+++ b/client/web/.env.development
@@ -0,0 +1,2 @@
+VITE_API_BASE=http://localhost:7777
+VITE_PB_BASE=http://localhost:8090
\ No newline at end of file
diff --git a/client/web/.env.production b/client/web/.env.production
new file mode 100644
index 0000000..8a5ae01
--- /dev/null
+++ b/client/web/.env.production
@@ -0,0 +1,2 @@
+VITE_API_BASE=http://localhost:7777
+VITE_PB_BASE=http://localhost:8090
\ No newline at end of file
diff --git a/client/web/.eslintrc.cjs b/client/web/.eslintrc.cjs
new file mode 100644
index 0000000..90cfe21
--- /dev/null
+++ b/client/web/.eslintrc.cjs
@@ -0,0 +1,13 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: ['eslint:recommended', 'plugin:react/recommended', 'plugin:react/jsx-runtime', 'plugin:react-hooks/recommended'],
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
+ parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
+ settings: { react: { version: '18.2' } },
+ plugins: ['react-refresh'],
+ rules: {
+ 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
+ 'react/prop-types': 'off',
+ },
+}
diff --git a/client/web/.gitignore b/client/web/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/client/web/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/client/web/README.md b/client/web/README.md
new file mode 100644
index 0000000..edeed30
--- /dev/null
+++ b/client/web/README.md
@@ -0,0 +1,6 @@
+web env:
+VITE_API_BASE=http://localhost:7777
+VITE_PB_BASE=http://localhost:8090
+
+pocketase env:
+AW_FILE_DIR=xxx
\ No newline at end of file
diff --git a/client/web/components.json b/client/web/components.json
new file mode 100644
index 0000000..92d235c
--- /dev/null
+++ b/client/web/components.json
@@ -0,0 +1,17 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "default",
+ "rsc": false,
+ "tsx": false,
+ "tailwind": {
+ "config": "tailwind.config.js",
+ "css": "src/index.css",
+ "baseColor": "slate",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@/components",
+ "utils": "@/lib/utils"
+ }
+}
\ No newline at end of file
diff --git a/client/web/index.html b/client/web/index.html
new file mode 100644
index 0000000..23b4f03
--- /dev/null
+++ b/client/web/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ 情报分析
+
+
+
+
+
+
diff --git a/client/web/package.json b/client/web/package.json
new file mode 100644
index 0000000..1bb8a36
--- /dev/null
+++ b/client/web/package.json
@@ -0,0 +1,56 @@
+{
+ "name": "asweb-react",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@hookform/resolvers": "^3.3.4",
+ "@radix-ui/react-accordion": "^1.1.2",
+ "@radix-ui/react-label": "^2.0.2",
+ "@radix-ui/react-slot": "^1.0.2",
+ "@radix-ui/react-toast": "^1.1.5",
+ "@rollup/rollup-linux-x64-gnu": "^4.9.6",
+ "@tanstack/react-query": "^5.17.9",
+ "@tanstack/react-query-devtools": "^5.17.9",
+ "axios": "^1.6.8",
+ "class-variance-authority": "^0.7.0",
+ "clsx": "^2.1.0",
+ "lucide-react": "^0.309.0",
+ "nanoid": "^5.0.4",
+ "pocketbase": "^0.21.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-hook-form": "^7.49.3",
+ "redaxios": "^0.5.1",
+ "tailwind-merge": "^2.2.0",
+ "tailwindcss-animate": "^1.0.7",
+ "wouter": "^3.1.0",
+ "zod": "^3.22.4",
+ "zustand": "^4.4.7"
+ },
+ "devDependencies": {
+ "@types/node": "^20.11.0",
+ "@types/react": "^18.2.43",
+ "@types/react-dom": "^18.2.17",
+ "@vitejs/plugin-react": "^4.2.1",
+ "autoprefixer": "^10.4.16",
+ "eslint": "^8.55.0",
+ "eslint-plugin-react": "^7.33.2",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-react-refresh": "^0.4.5",
+ "postcss": "^8.4.33",
+ "tailwindcss": "^3.4.1",
+ "vite": "^5.0.8"
+ },
+ "pnpm": {
+ "overrides": {
+ "rollup": "npm:@rollup/wasm-node"
+ }
+ }
+}
diff --git a/client/web/pnpm-lock.yaml b/client/web/pnpm-lock.yaml
new file mode 100644
index 0000000..e2be826
--- /dev/null
+++ b/client/web/pnpm-lock.yaml
@@ -0,0 +1,3374 @@
+lockfileVersion: '6.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+overrides:
+ rollup: npm:@rollup/wasm-node
+
+dependencies:
+ '@hookform/resolvers':
+ specifier: ^3.3.4
+ version: 3.3.4(react-hook-form@7.49.3)
+ '@radix-ui/react-accordion':
+ specifier: ^1.1.2
+ version: 1.1.2(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-label':
+ specifier: ^2.0.2
+ version: 2.0.2(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-slot':
+ specifier: ^1.0.2
+ version: 1.0.2(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-toast':
+ specifier: ^1.1.5
+ version: 1.1.5(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@rollup/rollup-linux-x64-gnu':
+ specifier: ^4.9.6
+ version: 4.9.6
+ '@tanstack/react-query':
+ specifier: ^5.17.9
+ version: 5.17.9(react@18.2.0)
+ '@tanstack/react-query-devtools':
+ specifier: ^5.17.9
+ version: 5.17.9(@tanstack/react-query@5.17.9)(react@18.2.0)
+ axios:
+ specifier: ^1.6.8
+ version: 1.6.8
+ class-variance-authority:
+ specifier: ^0.7.0
+ version: 0.7.0
+ clsx:
+ specifier: ^2.1.0
+ version: 2.1.0
+ lucide-react:
+ specifier: ^0.309.0
+ version: 0.309.0(react@18.2.0)
+ nanoid:
+ specifier: ^5.0.4
+ version: 5.0.4
+ pocketbase:
+ specifier: ^0.21.0
+ version: 0.21.0
+ react:
+ specifier: ^18.2.0
+ version: 18.2.0
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.2.0(react@18.2.0)
+ react-hook-form:
+ specifier: ^7.49.3
+ version: 7.49.3(react@18.2.0)
+ redaxios:
+ specifier: ^0.5.1
+ version: 0.5.1
+ tailwind-merge:
+ specifier: ^2.2.0
+ version: 2.2.0
+ tailwindcss-animate:
+ specifier: ^1.0.7
+ version: 1.0.7(tailwindcss@3.4.1)
+ wouter:
+ specifier: ^3.1.0
+ version: 3.1.0(react@18.2.0)
+ zod:
+ specifier: ^3.22.4
+ version: 3.22.4
+ zustand:
+ specifier: ^4.4.7
+ version: 4.4.7(@types/react@18.2.47)(react@18.2.0)
+
+devDependencies:
+ '@types/node':
+ specifier: ^20.11.0
+ version: 20.11.0
+ '@types/react':
+ specifier: ^18.2.43
+ version: 18.2.47
+ '@types/react-dom':
+ specifier: ^18.2.17
+ version: 18.2.18
+ '@vitejs/plugin-react':
+ specifier: ^4.2.1
+ version: 4.2.1(vite@5.0.11)
+ autoprefixer:
+ specifier: ^10.4.16
+ version: 10.4.16(postcss@8.4.33)
+ eslint:
+ specifier: ^8.55.0
+ version: 8.56.0
+ eslint-plugin-react:
+ specifier: ^7.33.2
+ version: 7.33.2(eslint@8.56.0)
+ eslint-plugin-react-hooks:
+ specifier: ^4.6.0
+ version: 4.6.0(eslint@8.56.0)
+ eslint-plugin-react-refresh:
+ specifier: ^0.4.5
+ version: 0.4.5(eslint@8.56.0)
+ postcss:
+ specifier: ^8.4.33
+ version: 8.4.33
+ tailwindcss:
+ specifier: ^3.4.1
+ version: 3.4.1
+ vite:
+ specifier: ^5.0.8
+ version: 5.0.11(@types/node@20.11.0)
+
+packages:
+
+ /@aashutoshrathi/word-wrap@1.2.6:
+ resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /@alloc/quick-lru@5.2.0:
+ resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
+ engines: {node: '>=10'}
+
+ /@ampproject/remapping@2.2.1:
+ resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/trace-mapping': 0.3.20
+ dev: true
+
+ /@babel/code-frame@7.23.5:
+ resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/highlight': 7.23.4
+ chalk: 2.4.2
+ dev: true
+
+ /@babel/compat-data@7.23.5:
+ resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/core@7.23.7:
+ resolution: {integrity: sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@ampproject/remapping': 2.2.1
+ '@babel/code-frame': 7.23.5
+ '@babel/generator': 7.23.6
+ '@babel/helper-compilation-targets': 7.23.6
+ '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.7)
+ '@babel/helpers': 7.23.8
+ '@babel/parser': 7.23.6
+ '@babel/template': 7.22.15
+ '@babel/traverse': 7.23.7
+ '@babel/types': 7.23.6
+ convert-source-map: 2.0.0
+ debug: 4.3.4
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/generator@7.23.6:
+ resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.6
+ '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/trace-mapping': 0.3.20
+ jsesc: 2.5.2
+ dev: true
+
+ /@babel/helper-compilation-targets@7.23.6:
+ resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/compat-data': 7.23.5
+ '@babel/helper-validator-option': 7.23.5
+ browserslist: 4.22.2
+ lru-cache: 5.1.1
+ semver: 6.3.1
+ dev: true
+
+ /@babel/helper-environment-visitor@7.22.20:
+ resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-function-name@7.23.0:
+ resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/template': 7.22.15
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/helper-hoist-variables@7.22.5:
+ resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/helper-module-imports@7.22.15:
+ resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.7):
+ resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.7
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-module-imports': 7.22.15
+ '@babel/helper-simple-access': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ '@babel/helper-validator-identifier': 7.22.20
+ dev: true
+
+ /@babel/helper-plugin-utils@7.22.5:
+ resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-simple-access@7.22.5:
+ resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/helper-split-export-declaration@7.22.6:
+ resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/helper-string-parser@7.23.4:
+ resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-validator-identifier@7.22.20:
+ resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-validator-option@7.23.5:
+ resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helpers@7.23.8:
+ resolution: {integrity: sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/template': 7.22.15
+ '@babel/traverse': 7.23.7
+ '@babel/types': 7.23.6
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/highlight@7.23.4:
+ resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-validator-identifier': 7.22.20
+ chalk: 2.4.2
+ js-tokens: 4.0.0
+ dev: true
+
+ /@babel/parser@7.23.6:
+ resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/plugin-transform-react-jsx-self@7.23.3(@babel/core@7.23.7):
+ resolution: {integrity: sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.7
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-react-jsx-source@7.23.3(@babel/core@7.23.7):
+ resolution: {integrity: sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.7
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/runtime@7.23.8:
+ resolution: {integrity: sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ regenerator-runtime: 0.14.1
+ dev: false
+
+ /@babel/template@7.22.15:
+ resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/code-frame': 7.23.5
+ '@babel/parser': 7.23.6
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@babel/traverse@7.23.7:
+ resolution: {integrity: sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/code-frame': 7.23.5
+ '@babel/generator': 7.23.6
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-function-name': 7.23.0
+ '@babel/helper-hoist-variables': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ '@babel/parser': 7.23.6
+ '@babel/types': 7.23.6
+ debug: 4.3.4
+ globals: 11.12.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/types@7.23.6:
+ resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-string-parser': 7.23.4
+ '@babel/helper-validator-identifier': 7.22.20
+ to-fast-properties: 2.0.0
+ dev: true
+
+ /@esbuild/aix-ppc64@0.19.11:
+ resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm64@0.19.11:
+ resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm@0.19.11:
+ resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-x64@0.19.11:
+ resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-arm64@0.19.11:
+ resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-x64@0.19.11:
+ resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-arm64@0.19.11:
+ resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-x64@0.19.11:
+ resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm64@0.19.11:
+ resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm@0.19.11:
+ resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ia32@0.19.11:
+ resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-loong64@0.19.11:
+ resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-mips64el@0.19.11:
+ resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ppc64@0.19.11:
+ resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-riscv64@0.19.11:
+ resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-s390x@0.19.11:
+ resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-x64@0.19.11:
+ resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/netbsd-x64@0.19.11:
+ resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/openbsd-x64@0.19.11:
+ resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/sunos-x64@0.19.11:
+ resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-arm64@0.19.11:
+ resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-ia32@0.19.11:
+ resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-x64@0.19.11:
+ resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0):
+ resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+ dependencies:
+ eslint: 8.56.0
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
+ /@eslint-community/regexpp@4.10.0:
+ resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==}
+ engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+ dev: true
+
+ /@eslint/eslintrc@2.1.4:
+ resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ ajv: 6.12.6
+ debug: 4.3.4
+ espree: 9.6.1
+ globals: 13.24.0
+ ignore: 5.3.0
+ import-fresh: 3.3.0
+ js-yaml: 4.1.0
+ minimatch: 3.1.2
+ strip-json-comments: 3.1.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@eslint/js@8.56.0:
+ resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /@hookform/resolvers@3.3.4(react-hook-form@7.49.3):
+ resolution: {integrity: sha512-o5cgpGOuJYrd+iMKvkttOclgwRW86EsWJZZRC23prf0uU2i48Htq4PuT73AVb9ionFyZrwYEITuOFGF+BydEtQ==}
+ peerDependencies:
+ react-hook-form: ^7.0.0
+ dependencies:
+ react-hook-form: 7.49.3(react@18.2.0)
+ dev: false
+
+ /@humanwhocodes/config-array@0.11.14:
+ resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
+ engines: {node: '>=10.10.0'}
+ dependencies:
+ '@humanwhocodes/object-schema': 2.0.2
+ debug: 4.3.4
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@humanwhocodes/module-importer@1.0.1:
+ resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+ engines: {node: '>=12.22'}
+ dev: true
+
+ /@humanwhocodes/object-schema@2.0.2:
+ resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==}
+ dev: true
+
+ /@isaacs/cliui@8.0.2:
+ resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+ engines: {node: '>=12'}
+ dependencies:
+ string-width: 5.1.2
+ string-width-cjs: /string-width@4.2.3
+ strip-ansi: 7.1.0
+ strip-ansi-cjs: /strip-ansi@6.0.1
+ wrap-ansi: 8.1.0
+ wrap-ansi-cjs: /wrap-ansi@7.0.0
+
+ /@jridgewell/gen-mapping@0.3.3:
+ resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/set-array': 1.1.2
+ '@jridgewell/sourcemap-codec': 1.4.15
+ '@jridgewell/trace-mapping': 0.3.20
+
+ /@jridgewell/resolve-uri@3.1.1:
+ resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
+ engines: {node: '>=6.0.0'}
+
+ /@jridgewell/set-array@1.1.2:
+ resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
+ engines: {node: '>=6.0.0'}
+
+ /@jridgewell/sourcemap-codec@1.4.15:
+ resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
+
+ /@jridgewell/trace-mapping@0.3.20:
+ resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==}
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.1
+ '@jridgewell/sourcemap-codec': 1.4.15
+
+ /@nodelib/fs.scandir@2.1.5:
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ /@nodelib/fs.stat@2.0.5:
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ /@nodelib/fs.walk@1.2.8:
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.16.0
+
+ /@pkgjs/parseargs@0.11.0:
+ resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+ engines: {node: '>=14'}
+ requiresBuild: true
+ optional: true
+
+ /@radix-ui/primitive@1.0.1:
+ resolution: {integrity: sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==}
+ dependencies:
+ '@babel/runtime': 7.23.8
+ dev: false
+
+ /@radix-ui/react-accordion@1.1.2(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-fDG7jcoNKVjSK6yfmuAs0EnPDro0WMXIhMtXdTBWqEioVW206ku+4Lw07e+13lUkFkpoEQ2PdeMIAGpdqEAmDg==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-collapsible': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-direction': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-id': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-collapsible@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-UBmVDkmR6IvDsloHVN+3rtx4Mi5TFvylYXpluuv0f37dtaz3H99bp8No0LGXRigVpl3UAT4l9j6bIchh42S/Gg==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-id': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-slot': 1.0.2(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-context@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-direction@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-dismissable-layer@1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-use-escape-keydown': 1.0.3(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-id@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-label@2.0.2(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-portal@1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-presence@1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-slot': 1.0.2(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-slot@1.0.2(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-toast@1.1.5(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-fRLn227WHIBRSzuRzGJ8W+5YALxofH23y0MlPLddaIpLpCDqdE0NZlS2NRQDRiptfxDeeCjgFIpexB1/zkxDlw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/primitive': 1.0.1
+ '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-context': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@radix-ui/react-use-callback-ref@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.47)(react@18.2.0)
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-use-layout-effect@1.0.1(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@types/react': 18.2.47
+ react: 18.2.0
+ dev: false
+
+ /@radix-ui/react-visually-hidden@1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0
+ react-dom: ^16.8 || ^17.0 || ^18.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ dependencies:
+ '@babel/runtime': 7.23.8
+ '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.18)(@types/react@18.2.47)(react-dom@18.2.0)(react@18.2.0)
+ '@types/react': 18.2.47
+ '@types/react-dom': 18.2.18
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@rollup/rollup-linux-x64-gnu@4.9.6:
+ resolution: {integrity: sha512-HUNqM32dGzfBKuaDUBqFB7tP6VMN74eLZ33Q9Y1TBqRDn+qDonkAUyKWwF9BR9unV7QUzffLnz9GrnKvMqC/fw==}
+ cpu: [x64]
+ os: [linux]
+ dev: false
+
+ /@rollup/wasm-node@4.13.2:
+ resolution: {integrity: sha512-4JXYomW63fBnXseG2mFkZwaNMDK0PkNamj9WD6H96FqEEl9ov3VjG3MK9UcOAj7Ap9o2weqSSCVng+QsxBeKfw==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+ dependencies:
+ '@types/estree': 1.0.5
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
+ /@tanstack/query-core@5.17.9:
+ resolution: {integrity: sha512-8xcvpWIPaRMDNLMvG9ugcUJMgFK316ZsqkPPbsI+TMZsb10N9jk0B6XgPk4/kgWC2ziHyWR7n7wUhxmD0pChQw==}
+ dev: false
+
+ /@tanstack/query-devtools@5.17.7:
+ resolution: {integrity: sha512-TfgvOqza5K7Sk6slxqkRIvXlEJoUoPSsGGwpuYSrpqgSwLSSvPPpZhq7hv7hcY5IvRoTNGoq6+MT01C/jILqoQ==}
+ dev: false
+
+ /@tanstack/react-query-devtools@5.17.9(@tanstack/react-query@5.17.9)(react@18.2.0):
+ resolution: {integrity: sha512-1viWP/jlO0LaeCdtTFqtF1k2RfM3KVpvwVffWv+PMNkS2u4s8YGUM17r3p82udbF9BY1mE7aHqQ3MM1errF5lQ==}
+ peerDependencies:
+ '@tanstack/react-query': ^5.17.9
+ react: ^18.0.0
+ dependencies:
+ '@tanstack/query-devtools': 5.17.7
+ '@tanstack/react-query': 5.17.9(react@18.2.0)
+ react: 18.2.0
+ dev: false
+
+ /@tanstack/react-query@5.17.9(react@18.2.0):
+ resolution: {integrity: sha512-M5E9gwUq1Stby/pdlYjBlL24euIVuGbWKIFCbtnQxSdXI4PgzjTSdXdV3QE6fc+itF+TUvX/JPTKIwq8yuBXcg==}
+ peerDependencies:
+ react: ^18.0.0
+ dependencies:
+ '@tanstack/query-core': 5.17.9
+ react: 18.2.0
+ dev: false
+
+ /@types/babel__core@7.20.5:
+ resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+ dependencies:
+ '@babel/parser': 7.23.6
+ '@babel/types': 7.23.6
+ '@types/babel__generator': 7.6.8
+ '@types/babel__template': 7.4.4
+ '@types/babel__traverse': 7.20.5
+ dev: true
+
+ /@types/babel__generator@7.6.8:
+ resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==}
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@types/babel__template@7.4.4:
+ resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+ dependencies:
+ '@babel/parser': 7.23.6
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@types/babel__traverse@7.20.5:
+ resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==}
+ dependencies:
+ '@babel/types': 7.23.6
+ dev: true
+
+ /@types/estree@1.0.5:
+ resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
+ dev: true
+
+ /@types/node@20.11.0:
+ resolution: {integrity: sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==}
+ dependencies:
+ undici-types: 5.26.5
+ dev: true
+
+ /@types/prop-types@15.7.11:
+ resolution: {integrity: sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==}
+
+ /@types/react-dom@18.2.18:
+ resolution: {integrity: sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==}
+ dependencies:
+ '@types/react': 18.2.47
+
+ /@types/react@18.2.47:
+ resolution: {integrity: sha512-xquNkkOirwyCgoClNk85BjP+aqnIS+ckAJ8i37gAbDs14jfW/J23f2GItAf33oiUPQnqNMALiFeoM9Y5mbjpVQ==}
+ dependencies:
+ '@types/prop-types': 15.7.11
+ '@types/scheduler': 0.16.8
+ csstype: 3.1.3
+
+ /@types/scheduler@0.16.8:
+ resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==}
+
+ /@ungap/structured-clone@1.2.0:
+ resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
+ dev: true
+
+ /@vitejs/plugin-react@4.2.1(vite@5.0.11):
+ resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.2.0 || ^5.0.0
+ dependencies:
+ '@babel/core': 7.23.7
+ '@babel/plugin-transform-react-jsx-self': 7.23.3(@babel/core@7.23.7)
+ '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.7)
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.14.0
+ vite: 5.0.11(@types/node@20.11.0)
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /acorn-jsx@5.3.2(acorn@8.11.3):
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+ dependencies:
+ acorn: 8.11.3
+ dev: true
+
+ /acorn@8.11.3:
+ resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+ dev: true
+
+ /ajv@6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+ dev: true
+
+ /ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ /ansi-regex@6.0.1:
+ resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
+ engines: {node: '>=12'}
+
+ /ansi-styles@3.2.1:
+ resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+ engines: {node: '>=4'}
+ dependencies:
+ color-convert: 1.9.3
+ dev: true
+
+ /ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+ dependencies:
+ color-convert: 2.0.1
+
+ /ansi-styles@6.2.1:
+ resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
+ engines: {node: '>=12'}
+
+ /any-promise@1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+
+ /anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+
+ /arg@5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+
+ /argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ dev: true
+
+ /array-buffer-byte-length@1.0.0:
+ resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==}
+ dependencies:
+ call-bind: 1.0.5
+ is-array-buffer: 3.0.2
+ dev: true
+
+ /array-includes@3.1.7:
+ resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ is-string: 1.0.7
+ dev: true
+
+ /array.prototype.flat@1.3.2:
+ resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-shim-unscopables: 1.0.2
+ dev: true
+
+ /array.prototype.flatmap@1.3.2:
+ resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-shim-unscopables: 1.0.2
+ dev: true
+
+ /array.prototype.tosorted@1.1.2:
+ resolution: {integrity: sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-shim-unscopables: 1.0.2
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /arraybuffer.prototype.slice@1.0.2:
+ resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ array-buffer-byte-length: 1.0.0
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ is-array-buffer: 3.0.2
+ is-shared-array-buffer: 1.0.2
+ dev: true
+
+ /asynciterator.prototype@1.0.0:
+ resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+ dev: false
+
+ /autoprefixer@10.4.16(postcss@8.4.33):
+ resolution: {integrity: sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==}
+ engines: {node: ^10 || ^12 || >=14}
+ hasBin: true
+ peerDependencies:
+ postcss: ^8.1.0
+ dependencies:
+ browserslist: 4.22.2
+ caniuse-lite: 1.0.30001576
+ fraction.js: 4.3.7
+ normalize-range: 0.1.2
+ picocolors: 1.0.0
+ postcss: 8.4.33
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /available-typed-arrays@1.0.5:
+ resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /axios@1.6.8:
+ resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==}
+ dependencies:
+ follow-redirects: 1.15.6
+ form-data: 4.0.0
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+ dev: false
+
+ /balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+ /binary-extensions@2.2.0:
+ resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
+ engines: {node: '>=8'}
+
+ /brace-expansion@1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+ dev: true
+
+ /brace-expansion@2.0.1:
+ resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+ dependencies:
+ balanced-match: 1.0.2
+
+ /braces@3.0.2:
+ resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+ engines: {node: '>=8'}
+ dependencies:
+ fill-range: 7.0.1
+
+ /browserslist@4.22.2:
+ resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+ dependencies:
+ caniuse-lite: 1.0.30001576
+ electron-to-chromium: 1.4.628
+ node-releases: 2.0.14
+ update-browserslist-db: 1.0.13(browserslist@4.22.2)
+ dev: true
+
+ /call-bind@1.0.5:
+ resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==}
+ dependencies:
+ function-bind: 1.1.2
+ get-intrinsic: 1.2.2
+ set-function-length: 1.1.1
+ dev: true
+
+ /callsites@3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /camelcase-css@2.0.1:
+ resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
+ engines: {node: '>= 6'}
+
+ /caniuse-lite@1.0.30001576:
+ resolution: {integrity: sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==}
+ dev: true
+
+ /chalk@2.4.2:
+ resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+ engines: {node: '>=4'}
+ dependencies:
+ ansi-styles: 3.2.1
+ escape-string-regexp: 1.0.5
+ supports-color: 5.5.0
+ dev: true
+
+ /chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+ dev: true
+
+ /chokidar@3.5.3:
+ resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
+ engines: {node: '>= 8.10.0'}
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.2
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ /class-variance-authority@0.7.0:
+ resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==}
+ dependencies:
+ clsx: 2.0.0
+ dev: false
+
+ /clsx@2.0.0:
+ resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==}
+ engines: {node: '>=6'}
+ dev: false
+
+ /clsx@2.1.0:
+ resolution: {integrity: sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==}
+ engines: {node: '>=6'}
+ dev: false
+
+ /color-convert@1.9.3:
+ resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+ dependencies:
+ color-name: 1.1.3
+ dev: true
+
+ /color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+ dependencies:
+ color-name: 1.1.4
+
+ /color-name@1.1.3:
+ resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+ dev: true
+
+ /color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ /combined-stream@1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+ dependencies:
+ delayed-stream: 1.0.0
+ dev: false
+
+ /commander@4.1.1:
+ resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+ engines: {node: '>= 6'}
+
+ /concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+ dev: true
+
+ /convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ dev: true
+
+ /cross-spawn@7.0.3:
+ resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+ engines: {node: '>= 8'}
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ /cssesc@3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ /csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
+ /debug@4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+ dev: true
+
+ /deep-is@0.1.4:
+ resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+ dev: true
+
+ /define-data-property@1.1.1:
+ resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.2
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.1
+ dev: true
+
+ /define-properties@1.2.1:
+ resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.1
+ has-property-descriptors: 1.0.1
+ object-keys: 1.1.1
+ dev: true
+
+ /delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+ dev: false
+
+ /didyoumean@1.2.2:
+ resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
+
+ /dlv@1.1.3:
+ resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
+
+ /doctrine@2.1.0:
+ resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ esutils: 2.0.3
+ dev: true
+
+ /doctrine@3.0.0:
+ resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ esutils: 2.0.3
+ dev: true
+
+ /eastasianwidth@0.2.0:
+ resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+
+ /electron-to-chromium@1.4.628:
+ resolution: {integrity: sha512-2k7t5PHvLsufpP6Zwk0nof62yLOsCf032wZx7/q0mv8gwlXjhcxI3lz6f0jBr0GrnWKcm3burXzI3t5IrcdUxw==}
+ dev: true
+
+ /emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
+ /emoji-regex@9.2.2:
+ resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+
+ /es-abstract@1.22.3:
+ resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ array-buffer-byte-length: 1.0.0
+ arraybuffer.prototype.slice: 1.0.2
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.5
+ es-set-tostringtag: 2.0.2
+ es-to-primitive: 1.2.1
+ function.prototype.name: 1.1.6
+ get-intrinsic: 1.2.2
+ get-symbol-description: 1.0.0
+ globalthis: 1.0.3
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.1
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ hasown: 2.0.0
+ internal-slot: 1.0.6
+ is-array-buffer: 3.0.2
+ is-callable: 1.2.7
+ is-negative-zero: 2.0.2
+ is-regex: 1.1.4
+ is-shared-array-buffer: 1.0.2
+ is-string: 1.0.7
+ is-typed-array: 1.1.12
+ is-weakref: 1.0.2
+ object-inspect: 1.13.1
+ object-keys: 1.1.1
+ object.assign: 4.1.5
+ regexp.prototype.flags: 1.5.1
+ safe-array-concat: 1.0.1
+ safe-regex-test: 1.0.1
+ string.prototype.trim: 1.2.8
+ string.prototype.trimend: 1.0.7
+ string.prototype.trimstart: 1.0.7
+ typed-array-buffer: 1.0.0
+ typed-array-byte-length: 1.0.0
+ typed-array-byte-offset: 1.0.0
+ typed-array-length: 1.0.4
+ unbox-primitive: 1.0.2
+ which-typed-array: 1.1.13
+ dev: true
+
+ /es-iterator-helpers@1.0.15:
+ resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==}
+ dependencies:
+ asynciterator.prototype: 1.0.0
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ es-set-tostringtag: 2.0.2
+ function-bind: 1.1.2
+ get-intrinsic: 1.2.2
+ globalthis: 1.0.3
+ has-property-descriptors: 1.0.1
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ internal-slot: 1.0.6
+ iterator.prototype: 1.1.2
+ safe-array-concat: 1.0.1
+ dev: true
+
+ /es-set-tostringtag@2.0.2:
+ resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.2
+ has-tostringtag: 1.0.0
+ hasown: 2.0.0
+ dev: true
+
+ /es-shim-unscopables@1.0.2:
+ resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==}
+ dependencies:
+ hasown: 2.0.0
+ dev: true
+
+ /es-to-primitive@1.2.1:
+ resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ is-callable: 1.2.7
+ is-date-object: 1.0.5
+ is-symbol: 1.0.4
+ dev: true
+
+ /esbuild@0.19.11:
+ resolution: {integrity: sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.19.11
+ '@esbuild/android-arm': 0.19.11
+ '@esbuild/android-arm64': 0.19.11
+ '@esbuild/android-x64': 0.19.11
+ '@esbuild/darwin-arm64': 0.19.11
+ '@esbuild/darwin-x64': 0.19.11
+ '@esbuild/freebsd-arm64': 0.19.11
+ '@esbuild/freebsd-x64': 0.19.11
+ '@esbuild/linux-arm': 0.19.11
+ '@esbuild/linux-arm64': 0.19.11
+ '@esbuild/linux-ia32': 0.19.11
+ '@esbuild/linux-loong64': 0.19.11
+ '@esbuild/linux-mips64el': 0.19.11
+ '@esbuild/linux-ppc64': 0.19.11
+ '@esbuild/linux-riscv64': 0.19.11
+ '@esbuild/linux-s390x': 0.19.11
+ '@esbuild/linux-x64': 0.19.11
+ '@esbuild/netbsd-x64': 0.19.11
+ '@esbuild/openbsd-x64': 0.19.11
+ '@esbuild/sunos-x64': 0.19.11
+ '@esbuild/win32-arm64': 0.19.11
+ '@esbuild/win32-ia32': 0.19.11
+ '@esbuild/win32-x64': 0.19.11
+ dev: true
+
+ /escalade@3.1.1:
+ resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /escape-string-regexp@1.0.5:
+ resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+ engines: {node: '>=0.8.0'}
+ dev: true
+
+ /escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /eslint-plugin-react-hooks@4.6.0(eslint@8.56.0):
+ resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
+ dependencies:
+ eslint: 8.56.0
+ dev: true
+
+ /eslint-plugin-react-refresh@0.4.5(eslint@8.56.0):
+ resolution: {integrity: sha512-D53FYKJa+fDmZMtriODxvhwrO+IOqrxoEo21gMA0sjHdU6dPVH4OhyFip9ypl8HOF5RV5KdTo+rBQLvnY2cO8w==}
+ peerDependencies:
+ eslint: '>=7'
+ dependencies:
+ eslint: 8.56.0
+ dev: true
+
+ /eslint-plugin-react@7.33.2(eslint@8.56.0):
+ resolution: {integrity: sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
+ dependencies:
+ array-includes: 3.1.7
+ array.prototype.flatmap: 1.3.2
+ array.prototype.tosorted: 1.1.2
+ doctrine: 2.1.0
+ es-iterator-helpers: 1.0.15
+ eslint: 8.56.0
+ estraverse: 5.3.0
+ jsx-ast-utils: 3.3.5
+ minimatch: 3.1.2
+ object.entries: 1.1.7
+ object.fromentries: 2.0.7
+ object.hasown: 1.1.3
+ object.values: 1.1.7
+ prop-types: 15.8.1
+ resolve: 2.0.0-next.5
+ semver: 6.3.1
+ string.prototype.matchall: 4.0.10
+ dev: true
+
+ /eslint-scope@7.2.2:
+ resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+ dev: true
+
+ /eslint-visitor-keys@3.4.3:
+ resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /eslint@8.56.0:
+ resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ hasBin: true
+ dependencies:
+ '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0)
+ '@eslint-community/regexpp': 4.10.0
+ '@eslint/eslintrc': 2.1.4
+ '@eslint/js': 8.56.0
+ '@humanwhocodes/config-array': 0.11.14
+ '@humanwhocodes/module-importer': 1.0.1
+ '@nodelib/fs.walk': 1.2.8
+ '@ungap/structured-clone': 1.2.0
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.3
+ debug: 4.3.4
+ doctrine: 3.0.0
+ escape-string-regexp: 4.0.0
+ eslint-scope: 7.2.2
+ eslint-visitor-keys: 3.4.3
+ espree: 9.6.1
+ esquery: 1.5.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 6.0.1
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ globals: 13.24.0
+ graphemer: 1.4.0
+ ignore: 5.3.0
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ is-path-inside: 3.0.3
+ js-yaml: 4.1.0
+ json-stable-stringify-without-jsonify: 1.0.1
+ levn: 0.4.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.3
+ strip-ansi: 6.0.1
+ text-table: 0.2.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /espree@9.6.1:
+ resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ acorn: 8.11.3
+ acorn-jsx: 5.3.2(acorn@8.11.3)
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
+ /esquery@1.5.0:
+ resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
+ engines: {node: '>=0.10'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /esrecurse@4.3.0:
+ resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+ engines: {node: '>=4.0'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /estraverse@5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+ dev: true
+
+ /esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+ dev: true
+
+ /fast-glob@3.3.2:
+ resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
+ engines: {node: '>=8.6.0'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.5
+
+ /fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+ dev: true
+
+ /fast-levenshtein@2.0.6:
+ resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+ dev: true
+
+ /fastq@1.16.0:
+ resolution: {integrity: sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==}
+ dependencies:
+ reusify: 1.0.4
+
+ /file-entry-cache@6.0.1:
+ resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+ dependencies:
+ flat-cache: 3.2.0
+ dev: true
+
+ /fill-range@7.0.1:
+ resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ to-regex-range: 5.0.1
+
+ /find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+ dev: true
+
+ /flat-cache@3.2.0:
+ resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+ dependencies:
+ flatted: 3.2.9
+ keyv: 4.5.4
+ rimraf: 3.0.2
+ dev: true
+
+ /flatted@3.2.9:
+ resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==}
+ dev: true
+
+ /follow-redirects@1.15.6:
+ resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+ dev: false
+
+ /for-each@0.3.3:
+ resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
+ dependencies:
+ is-callable: 1.2.7
+ dev: true
+
+ /foreground-child@3.1.1:
+ resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
+ engines: {node: '>=14'}
+ dependencies:
+ cross-spawn: 7.0.3
+ signal-exit: 4.1.0
+
+ /form-data@4.0.0:
+ resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
+ engines: {node: '>= 6'}
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ mime-types: 2.1.35
+ dev: false
+
+ /fraction.js@4.3.7:
+ resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
+ dev: true
+
+ /fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+ dev: true
+
+ /fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ optional: true
+
+ /function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ /function.prototype.name@1.1.6:
+ resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ functions-have-names: 1.2.3
+ dev: true
+
+ /functions-have-names@1.2.3:
+ resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+ dev: true
+
+ /gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /get-intrinsic@1.2.2:
+ resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==}
+ dependencies:
+ function-bind: 1.1.2
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ hasown: 2.0.0
+ dev: true
+
+ /get-symbol-description@1.0.0:
+ resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+ dependencies:
+ is-glob: 4.0.3
+
+ /glob-parent@6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+ dependencies:
+ is-glob: 4.0.3
+
+ /glob@10.3.10:
+ resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+ dependencies:
+ foreground-child: 3.1.1
+ jackspeak: 2.3.6
+ minimatch: 9.0.3
+ minipass: 7.0.4
+ path-scurry: 1.10.1
+
+ /glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+ dev: true
+
+ /globals@11.12.0:
+ resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /globals@13.24.0:
+ resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ type-fest: 0.20.2
+ dev: true
+
+ /globalthis@1.0.3:
+ resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-properties: 1.2.1
+ dev: true
+
+ /gopd@1.0.1:
+ resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
+ dependencies:
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /graphemer@1.4.0:
+ resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+ dev: true
+
+ /has-bigints@1.0.2:
+ resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
+ dev: true
+
+ /has-flag@3.0.0:
+ resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /has-property-descriptors@1.0.1:
+ resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==}
+ dependencies:
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /has-proto@1.0.1:
+ resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-symbols@1.0.3:
+ resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-tostringtag@1.0.0:
+ resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /hasown@2.0.0:
+ resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ function-bind: 1.1.2
+
+ /ignore@5.3.0:
+ resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==}
+ engines: {node: '>= 4'}
+ dev: true
+
+ /import-fresh@3.3.0:
+ resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+ engines: {node: '>=6'}
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+ dev: true
+
+ /imurmurhash@0.1.4:
+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+ engines: {node: '>=0.8.19'}
+ dev: true
+
+ /inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+ dev: true
+
+ /inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ dev: true
+
+ /internal-slot@1.0.6:
+ resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.2.2
+ hasown: 2.0.0
+ side-channel: 1.0.4
+ dev: true
+
+ /is-array-buffer@3.0.2:
+ resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ is-typed-array: 1.1.12
+ dev: true
+
+ /is-async-function@2.0.0:
+ resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-bigint@1.0.4:
+ resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
+ dependencies:
+ has-bigints: 1.0.2
+ dev: true
+
+ /is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+ dependencies:
+ binary-extensions: 2.2.0
+
+ /is-boolean-object@1.1.2:
+ resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-callable@1.2.7:
+ resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-core-module@2.13.1:
+ resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
+ dependencies:
+ hasown: 2.0.0
+
+ /is-date-object@1.0.5:
+ resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ /is-finalizationregistry@1.0.2:
+ resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==}
+ dependencies:
+ call-bind: 1.0.5
+ dev: true
+
+ /is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+
+ /is-generator-function@1.0.10:
+ resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ is-extglob: 2.1.1
+
+ /is-map@2.0.2:
+ resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==}
+ dev: true
+
+ /is-negative-zero@2.0.2:
+ resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-number-object@1.0.7:
+ resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ /is-path-inside@3.0.3:
+ resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-regex@1.1.4:
+ resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-set@2.0.2:
+ resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==}
+ dev: true
+
+ /is-shared-array-buffer@1.0.2:
+ resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==}
+ dependencies:
+ call-bind: 1.0.5
+ dev: true
+
+ /is-string@1.0.7:
+ resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /is-symbol@1.0.4:
+ resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.0.3
+ dev: true
+
+ /is-typed-array@1.1.12:
+ resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ which-typed-array: 1.1.13
+ dev: true
+
+ /is-weakmap@2.0.1:
+ resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==}
+ dev: true
+
+ /is-weakref@1.0.2:
+ resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
+ dependencies:
+ call-bind: 1.0.5
+ dev: true
+
+ /is-weakset@2.0.2:
+ resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ dev: true
+
+ /isarray@2.0.5:
+ resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
+ dev: true
+
+ /isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ /iterator.prototype@1.1.2:
+ resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==}
+ dependencies:
+ define-properties: 1.2.1
+ get-intrinsic: 1.2.2
+ has-symbols: 1.0.3
+ reflect.getprototypeof: 1.0.4
+ set-function-name: 2.0.1
+ dev: true
+
+ /jackspeak@2.3.6:
+ resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
+ engines: {node: '>=14'}
+ dependencies:
+ '@isaacs/cliui': 8.0.2
+ optionalDependencies:
+ '@pkgjs/parseargs': 0.11.0
+
+ /jiti@1.21.0:
+ resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==}
+ hasBin: true
+
+ /js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ /js-yaml@4.1.0:
+ resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ dev: true
+
+ /jsesc@2.5.2:
+ resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
+ engines: {node: '>=4'}
+ hasBin: true
+ dev: true
+
+ /json-buffer@3.0.1:
+ resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+ dev: true
+
+ /json-schema-traverse@0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+ dev: true
+
+ /json-stable-stringify-without-jsonify@1.0.1:
+ resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+ dev: true
+
+ /json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+ dev: true
+
+ /jsx-ast-utils@3.3.5:
+ resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
+ engines: {node: '>=4.0'}
+ dependencies:
+ array-includes: 3.1.7
+ array.prototype.flat: 1.3.2
+ object.assign: 4.1.5
+ object.values: 1.1.7
+ dev: true
+
+ /keyv@4.5.4:
+ resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+ dependencies:
+ json-buffer: 3.0.1
+ dev: true
+
+ /levn@0.4.1:
+ resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ dev: true
+
+ /lilconfig@2.1.0:
+ resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
+ engines: {node: '>=10'}
+
+ /lilconfig@3.0.0:
+ resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==}
+ engines: {node: '>=14'}
+
+ /lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+
+ /locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-locate: 5.0.0
+ dev: true
+
+ /lodash.merge@4.6.2:
+ resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ dev: true
+
+ /loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+ dependencies:
+ js-tokens: 4.0.0
+
+ /lru-cache@10.1.0:
+ resolution: {integrity: sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==}
+ engines: {node: 14 || >=16.14}
+
+ /lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+ dependencies:
+ yallist: 3.1.1
+ dev: true
+
+ /lucide-react@0.309.0(react@18.2.0):
+ resolution: {integrity: sha512-zNVPczuwFrCfksZH3zbd1UDE6/WYhYAdbe2k7CImVyPAkXLgIwbs6eXQ4loigqDnUFjyFYCI5jZ1y10Kqal0dg==}
+ peerDependencies:
+ react: ^16.5.1 || ^17.0.0 || ^18.0.0
+ dependencies:
+ react: 18.2.0
+ dev: false
+
+ /merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ /micromatch@4.0.5:
+ resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ braces: 3.0.2
+ picomatch: 2.3.1
+
+ /mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+ dev: false
+
+ /mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+ dependencies:
+ mime-db: 1.52.0
+ dev: false
+
+ /minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ dependencies:
+ brace-expansion: 1.1.11
+ dev: true
+
+ /minimatch@9.0.3:
+ resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dependencies:
+ brace-expansion: 2.0.1
+
+ /minipass@7.0.4:
+ resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ /mitt@3.0.1:
+ resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
+ dev: false
+
+ /ms@2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+ dev: true
+
+ /mz@2.7.0:
+ resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+ dependencies:
+ any-promise: 1.3.0
+ object-assign: 4.1.1
+ thenify-all: 1.6.0
+
+ /nanoid@3.3.7:
+ resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ /nanoid@5.0.4:
+ resolution: {integrity: sha512-vAjmBf13gsmhXSgBrtIclinISzFFy22WwCYoyilZlsrRXNIHSwgFQ1bEdjRwMT3aoadeIF6HMuDRlOxzfXV8ig==}
+ engines: {node: ^18 || >=20}
+ hasBin: true
+ dev: false
+
+ /natural-compare@1.4.0:
+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ dev: true
+
+ /node-releases@2.0.14:
+ resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
+ dev: true
+
+ /normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+
+ /normalize-range@0.1.2:
+ resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ /object-hash@3.0.0:
+ resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
+ engines: {node: '>= 6'}
+
+ /object-inspect@1.13.1:
+ resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
+ dev: true
+
+ /object-keys@1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /object.assign@4.1.5:
+ resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ has-symbols: 1.0.3
+ object-keys: 1.1.1
+ dev: true
+
+ /object.entries@1.1.7:
+ resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /object.fromentries@2.0.7:
+ resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /object.hasown@1.1.3:
+ resolution: {integrity: sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==}
+ dependencies:
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /object.values@1.1.7:
+ resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+ dependencies:
+ wrappy: 1.0.2
+ dev: true
+
+ /optionator@0.9.3:
+ resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ '@aashutoshrathi/word-wrap': 1.2.6
+ deep-is: 0.1.4
+ fast-levenshtein: 2.0.6
+ levn: 0.4.1
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ dev: true
+
+ /p-limit@3.1.0:
+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ yocto-queue: 0.1.0
+ dev: true
+
+ /p-locate@5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-limit: 3.1.0
+ dev: true
+
+ /parent-module@1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+ dependencies:
+ callsites: 3.1.0
+ dev: true
+
+ /path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ /path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+ /path-scurry@1.10.1:
+ resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dependencies:
+ lru-cache: 10.1.0
+ minipass: 7.0.4
+
+ /picocolors@1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+
+ /picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+
+ /pify@2.3.0:
+ resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
+ engines: {node: '>=0.10.0'}
+
+ /pirates@4.0.6:
+ resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
+ engines: {node: '>= 6'}
+
+ /pocketbase@0.21.0:
+ resolution: {integrity: sha512-WGA5qxW9jzwOTx0i3FNhkKBlT2F5EvC8qZDYv14SB3BeOZVAqs6wMTj7vAXD52V0Fg8zF4XPHJCAJK04fw1rqg==}
+ dev: false
+
+ /postcss-import@15.1.0(postcss@8.4.33):
+ resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ postcss: ^8.0.0
+ dependencies:
+ postcss: 8.4.33
+ postcss-value-parser: 4.2.0
+ read-cache: 1.0.0
+ resolve: 1.22.8
+
+ /postcss-js@4.0.1(postcss@8.4.33):
+ resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
+ engines: {node: ^12 || ^14 || >= 16}
+ peerDependencies:
+ postcss: ^8.4.21
+ dependencies:
+ camelcase-css: 2.0.1
+ postcss: 8.4.33
+
+ /postcss-load-config@4.0.2(postcss@8.4.33):
+ resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
+ engines: {node: '>= 14'}
+ peerDependencies:
+ postcss: '>=8.0.9'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ postcss:
+ optional: true
+ ts-node:
+ optional: true
+ dependencies:
+ lilconfig: 3.0.0
+ postcss: 8.4.33
+ yaml: 2.3.4
+
+ /postcss-nested@6.0.1(postcss@8.4.33):
+ resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==}
+ engines: {node: '>=12.0'}
+ peerDependencies:
+ postcss: ^8.2.14
+ dependencies:
+ postcss: 8.4.33
+ postcss-selector-parser: 6.0.15
+
+ /postcss-selector-parser@6.0.15:
+ resolution: {integrity: sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==}
+ engines: {node: '>=4'}
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+
+ /postcss-value-parser@4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+
+ /postcss@8.4.33:
+ resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+
+ /prelude-ls@1.2.1:
+ resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+ engines: {node: '>= 0.8.0'}
+ dev: true
+
+ /prop-types@15.8.1:
+ resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ dependencies:
+ loose-envify: 1.4.0
+ object-assign: 4.1.1
+ react-is: 16.13.1
+ dev: true
+
+ /proxy-from-env@1.1.0:
+ resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+ dev: false
+
+ /punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+ /react-dom@18.2.0(react@18.2.0):
+ resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
+ peerDependencies:
+ react: ^18.2.0
+ dependencies:
+ loose-envify: 1.4.0
+ react: 18.2.0
+ scheduler: 0.23.0
+ dev: false
+
+ /react-hook-form@7.49.3(react@18.2.0):
+ resolution: {integrity: sha512-foD6r3juidAT1cOZzpmD/gOKt7fRsDhXXZ0y28+Al1CHgX+AY1qIN9VSIIItXRq1dN68QrRwl1ORFlwjBaAqeQ==}
+ engines: {node: '>=18', pnpm: '8'}
+ peerDependencies:
+ react: ^16.8.0 || ^17 || ^18
+ dependencies:
+ react: 18.2.0
+ dev: false
+
+ /react-is@16.13.1:
+ resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
+ dev: true
+
+ /react-refresh@0.14.0:
+ resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /react@18.2.0:
+ resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: false
+
+ /read-cache@1.0.0:
+ resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
+ dependencies:
+ pify: 2.3.0
+
+ /readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+ dependencies:
+ picomatch: 2.3.1
+
+ /redaxios@0.5.1:
+ resolution: {integrity: sha512-FSD2AmfdbkYwl7KDExYQlVvIrFz6Yd83pGfaGjBzM9F6rpq8g652Q4Yq5QD4c+nf4g2AgeElv1y+8ajUPiOYMg==}
+ dev: false
+
+ /reflect.getprototypeof@1.0.4:
+ resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ globalthis: 1.0.3
+ which-builtin-type: 1.1.3
+ dev: true
+
+ /regenerator-runtime@0.14.1:
+ resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
+ dev: false
+
+ /regexp.prototype.flags@1.5.1:
+ resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ set-function-name: 2.0.1
+ dev: true
+
+ /regexparam@3.0.0:
+ resolution: {integrity: sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==}
+ engines: {node: '>=8'}
+ dev: false
+
+ /resolve-from@4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /resolve@1.22.8:
+ resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.13.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
+ /resolve@2.0.0-next.5:
+ resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.13.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
+ /reusify@1.0.4:
+ resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ /rimraf@3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ hasBin: true
+ dependencies:
+ glob: 7.2.3
+ dev: true
+
+ /run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ dependencies:
+ queue-microtask: 1.2.3
+
+ /safe-array-concat@1.0.1:
+ resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==}
+ engines: {node: '>=0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ has-symbols: 1.0.3
+ isarray: 2.0.5
+ dev: true
+
+ /safe-regex-test@1.0.1:
+ resolution: {integrity: sha512-Y5NejJTTliTyY4H7sipGqY+RX5P87i3F7c4Rcepy72nq+mNLhIsD0W4c7kEmduMDQCSqtPsXPlSTsFhh2LQv+g==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ is-regex: 1.1.4
+ dev: true
+
+ /scheduler@0.23.0:
+ resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: false
+
+ /semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+ dev: true
+
+ /set-function-length@1.1.1:
+ resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.1
+ get-intrinsic: 1.2.2
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.1
+ dev: true
+
+ /set-function-name@2.0.1:
+ resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.1
+ functions-have-names: 1.2.3
+ has-property-descriptors: 1.0.1
+ dev: true
+
+ /shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+ dependencies:
+ shebang-regex: 3.0.0
+
+ /shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ /side-channel@1.0.4:
+ resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ object-inspect: 1.13.1
+ dev: true
+
+ /signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+
+ /source-map-js@1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+
+ /string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+
+ /string-width@5.1.2:
+ resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+ engines: {node: '>=12'}
+ dependencies:
+ eastasianwidth: 0.2.0
+ emoji-regex: 9.2.2
+ strip-ansi: 7.1.0
+
+ /string.prototype.matchall@4.0.10:
+ resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ get-intrinsic: 1.2.2
+ has-symbols: 1.0.3
+ internal-slot: 1.0.6
+ regexp.prototype.flags: 1.5.1
+ set-function-name: 2.0.1
+ side-channel: 1.0.4
+ dev: true
+
+ /string.prototype.trim@1.2.8:
+ resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /string.prototype.trimend@1.0.7:
+ resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /string.prototype.trimstart@1.0.7:
+ resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==}
+ dependencies:
+ call-bind: 1.0.5
+ define-properties: 1.2.1
+ es-abstract: 1.22.3
+ dev: true
+
+ /strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-regex: 5.0.1
+
+ /strip-ansi@7.1.0:
+ resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-regex: 6.0.1
+
+ /strip-json-comments@3.1.1:
+ resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /sucrase@3.35.0:
+ resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.3
+ commander: 4.1.1
+ glob: 10.3.10
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.6
+ ts-interface-checker: 0.1.13
+
+ /supports-color@5.5.0:
+ resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+ engines: {node: '>=4'}
+ dependencies:
+ has-flag: 3.0.0
+ dev: true
+
+ /supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+
+ /tailwind-merge@2.2.0:
+ resolution: {integrity: sha512-SqqhhaL0T06SW59+JVNfAqKdqLs0497esifRrZ7jOaefP3o64fdFNDMrAQWZFMxTLJPiHVjRLUywT8uFz1xNWQ==}
+ dependencies:
+ '@babel/runtime': 7.23.8
+ dev: false
+
+ /tailwindcss-animate@1.0.7(tailwindcss@3.4.1):
+ resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==}
+ peerDependencies:
+ tailwindcss: '>=3.0.0 || insiders'
+ dependencies:
+ tailwindcss: 3.4.1
+ dev: false
+
+ /tailwindcss@3.4.1:
+ resolution: {integrity: sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+ dependencies:
+ '@alloc/quick-lru': 5.2.0
+ arg: 5.0.2
+ chokidar: 3.5.3
+ didyoumean: 1.2.2
+ dlv: 1.1.3
+ fast-glob: 3.3.2
+ glob-parent: 6.0.2
+ is-glob: 4.0.3
+ jiti: 1.21.0
+ lilconfig: 2.1.0
+ micromatch: 4.0.5
+ normalize-path: 3.0.0
+ object-hash: 3.0.0
+ picocolors: 1.0.0
+ postcss: 8.4.33
+ postcss-import: 15.1.0(postcss@8.4.33)
+ postcss-js: 4.0.1(postcss@8.4.33)
+ postcss-load-config: 4.0.2(postcss@8.4.33)
+ postcss-nested: 6.0.1(postcss@8.4.33)
+ postcss-selector-parser: 6.0.15
+ resolve: 1.22.8
+ sucrase: 3.35.0
+ transitivePeerDependencies:
+ - ts-node
+
+ /text-table@0.2.0:
+ resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+ dev: true
+
+ /thenify-all@1.6.0:
+ resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+ engines: {node: '>=0.8'}
+ dependencies:
+ thenify: 3.3.1
+
+ /thenify@3.3.1:
+ resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+ dependencies:
+ any-promise: 1.3.0
+
+ /to-fast-properties@2.0.0:
+ resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+ dependencies:
+ is-number: 7.0.0
+
+ /ts-interface-checker@0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+
+ /type-check@0.4.0:
+ resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ dev: true
+
+ /type-fest@0.20.2:
+ resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /typed-array-buffer@1.0.0:
+ resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ get-intrinsic: 1.2.2
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-byte-length@1.0.0:
+ resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ has-proto: 1.0.1
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-byte-offset@1.0.0:
+ resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ has-proto: 1.0.1
+ is-typed-array: 1.1.12
+ dev: true
+
+ /typed-array-length@1.0.4:
+ resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==}
+ dependencies:
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ is-typed-array: 1.1.12
+ dev: true
+
+ /unbox-primitive@1.0.2:
+ resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
+ dependencies:
+ call-bind: 1.0.5
+ has-bigints: 1.0.2
+ has-symbols: 1.0.3
+ which-boxed-primitive: 1.0.2
+ dev: true
+
+ /undici-types@5.26.5:
+ resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+ dev: true
+
+ /update-browserslist-db@1.0.13(browserslist@4.22.2):
+ resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+ dependencies:
+ browserslist: 4.22.2
+ escalade: 3.1.1
+ picocolors: 1.0.0
+ dev: true
+
+ /uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ dependencies:
+ punycode: 2.3.1
+ dev: true
+
+ /use-sync-external-store@1.2.0(react@18.2.0):
+ resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ dependencies:
+ react: 18.2.0
+ dev: false
+
+ /util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+ /vite@5.0.11(@types/node@20.11.0):
+ resolution: {integrity: sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || >=20.0.0
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ dependencies:
+ '@types/node': 20.11.0
+ esbuild: 0.19.11
+ postcss: 8.4.33
+ rollup: /@rollup/wasm-node@4.13.2
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
+ /which-boxed-primitive@1.0.2:
+ resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
+ dependencies:
+ is-bigint: 1.0.4
+ is-boolean-object: 1.1.2
+ is-number-object: 1.0.7
+ is-string: 1.0.7
+ is-symbol: 1.0.4
+ dev: true
+
+ /which-builtin-type@1.1.3:
+ resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ function.prototype.name: 1.1.6
+ has-tostringtag: 1.0.0
+ is-async-function: 2.0.0
+ is-date-object: 1.0.5
+ is-finalizationregistry: 1.0.2
+ is-generator-function: 1.0.10
+ is-regex: 1.1.4
+ is-weakref: 1.0.2
+ isarray: 2.0.5
+ which-boxed-primitive: 1.0.2
+ which-collection: 1.0.1
+ which-typed-array: 1.1.13
+ dev: true
+
+ /which-collection@1.0.1:
+ resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==}
+ dependencies:
+ is-map: 2.0.2
+ is-set: 2.0.2
+ is-weakmap: 2.0.1
+ is-weakset: 2.0.2
+ dev: true
+
+ /which-typed-array@1.1.13:
+ resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.5
+ call-bind: 1.0.5
+ for-each: 0.3.3
+ gopd: 1.0.1
+ has-tostringtag: 1.0.0
+ dev: true
+
+ /which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+ dependencies:
+ isexe: 2.0.0
+
+ /wouter@3.1.0(react@18.2.0):
+ resolution: {integrity: sha512-hou3w+12BMTBckdWdyJp/z7+kKcbdLDWfz6omSyrO6bbx4irNuQQyLDQkfSGXXJCxmglea3c8On9XFUkBSU8+Q==}
+ peerDependencies:
+ react: '>=16.8.0'
+ dependencies:
+ mitt: 3.0.1
+ react: 18.2.0
+ regexparam: 3.0.0
+ use-sync-external-store: 1.2.0(react@18.2.0)
+ dev: false
+
+ /wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ /wrap-ansi@8.1.0:
+ resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-styles: 6.2.1
+ string-width: 5.1.2
+ strip-ansi: 7.1.0
+
+ /wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+ dev: true
+
+ /yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+ dev: true
+
+ /yaml@2.3.4:
+ resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==}
+ engines: {node: '>= 14'}
+
+ /yocto-queue@0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /zod@3.22.4:
+ resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}
+ dev: false
+
+ /zustand@4.4.7(@types/react@18.2.47)(react@18.2.0):
+ resolution: {integrity: sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==}
+ engines: {node: '>=12.7.0'}
+ peerDependencies:
+ '@types/react': '>=16.8'
+ immer: '>=9.0'
+ react: '>=16.8'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ immer:
+ optional: true
+ react:
+ optional: true
+ dependencies:
+ '@types/react': 18.2.47
+ react: 18.2.0
+ use-sync-external-store: 1.2.0(react@18.2.0)
+ dev: false
diff --git a/client/web/postcss.config.js b/client/web/postcss.config.js
new file mode 100644
index 0000000..2e7af2b
--- /dev/null
+++ b/client/web/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/client/web/public/vite.svg b/client/web/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/client/web/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/web/src/App.css b/client/web/src/App.css
new file mode 100644
index 0000000..917a0a9
--- /dev/null
+++ b/client/web/src/App.css
@@ -0,0 +1,13 @@
+#root {
+ max-width: 1280px;
+ min-height: 100%;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+html,
+body {
+ width: 100%;
+ height: 100%;
+}
diff --git a/client/web/src/App.jsx b/client/web/src/App.jsx
new file mode 100644
index 0000000..ca23aef
--- /dev/null
+++ b/client/web/src/App.jsx
@@ -0,0 +1,54 @@
+import { QueryClient, QueryClientProvider, QueryCache, useQueryClient } from "@tanstack/react-query"
+import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
+
+import "./App.css"
+
+import { Toaster } from "@/components/ui/toaster"
+import { useToast } from "@/components/ui/use-toast"
+import { Button } from "@/components/ui/button"
+import LoginScreen from "@/components/screen/login"
+// import Steps from "@/components/screen/steps"
+import InsightsScreen from "@/components/screen/insights"
+import ArticlesScreen from "@/components/screen/articles"
+import ReportScreen from "@/components/screen/report"
+
+import { isAuth } from "@/store"
+
+const queryClient = new QueryClient()
+
+import { Route, Switch, useLocation } from "wouter"
+
+function App() {
+ const [, setLocation] = useLocation()
+ if (!isAuth()) {
+ setLocation("/login")
+ }
+ // const { toast } = useToast()
+
+ return (
+
+
+
+
+
+
+
+ 404
+
+ {/* {
+ toast({
+ title: "Scheduled: Catch up",
+ description: "Friday, February 10, 2023 at 5:57 PM",
+ })
+ }}
+ >
+ Show Toast
+ */}
+
+
+
+ )
+}
+
+export default App
diff --git a/client/web/src/assets/react.svg b/client/web/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/client/web/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/web/src/components/article-list.jsx b/client/web/src/components/article-list.jsx
new file mode 100644
index 0000000..6bf6867
--- /dev/null
+++ b/client/web/src/components/article-list.jsx
@@ -0,0 +1,33 @@
+import { Button } from "@/components/ui/button"
+import { Delete } from "lucide-react"
+
+// data expecting object {"0":{}, "1":{}}
+export function ArticleList({ data, showActions, onDelete }) {
+ return (
+
+
+ {data &&
+ data.map((article, i) => (
+
+
+
+ {showActions && (
+ onDelete(article.id)}>
+
+
+ )}
+
+
+ ))}
+
+ {data &&
共{Object.keys(data).length}篇文章
}
+
+ )
+}
diff --git a/client/web/src/components/layout/step.jsx b/client/web/src/components/layout/step.jsx
new file mode 100644
index 0000000..b329913
--- /dev/null
+++ b/client/web/src/components/layout/step.jsx
@@ -0,0 +1,21 @@
+import { Button } from "@/components/ui/button"
+
+export default function StepLayout({ title, description, children, navigate }) {
+ return (
+ <>
+
+
+
+
{title}
+ {description &&
{description}
}
+
+ {/*
navigate("/start")}>
+ 新建任务
+ */}
+
+
+ {children}
+
+ >
+ )
+}
diff --git a/client/web/src/components/screen/articles.jsx b/client/web/src/components/screen/articles.jsx
new file mode 100644
index 0000000..2c3045f
--- /dev/null
+++ b/client/web/src/components/screen/articles.jsx
@@ -0,0 +1,74 @@
+import { useEffect } from "react"
+import { Button } from "@/components/ui/button"
+import { ArticleList } from "../article-list"
+import { useMutation, useQueryClient } from "@tanstack/react-query"
+import { Languages } from "lucide-react"
+import { ButtonLoading } from "@/components/ui/button-loading"
+import { useDatePager, useArticleDates, useArticles, translations } from "@/store"
+
+import { useLocation } from "wouter"
+
+function ArticlesScreen({}) {
+ const [, navigate] = useLocation()
+
+ const queryDates = useArticleDates()
+ const { index, last, next, hasLast, hasNext } = useDatePager(queryDates.data)
+ const currentDate = queryDates.data && index >= 0 ? queryDates.data[index] : ""
+ const query = useArticles(currentDate)
+ const queryClient = useQueryClient()
+
+ const mut = useMutation({
+ mutationFn: (data) => {
+ return translations(data)
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ["articles", currentDate] })
+ },
+ })
+
+ function trans() {
+ mut.mutate({ article_ids: query.data.map((d) => d.id) })
+ }
+
+ return (
+ <>
+ 文章
+ {query.isError && {query.error.message}
}
+
+ navigate("/insights")}>查看分析结果
+ {mut.isPending && }
+ {!mut.isPending && query.data && query.data.length > 0 && query.data.filter((a) => !a.translation_result).length > 0 && (
+
+
+ 一键翻译
+
+ )}
+
+ {currentDate && (
+
+
+ <
+
+
{currentDate}
+
+ >
+
+
+ )}
+ {/* {completed && !Object.values(query.data.articles)[0]["zh-cn"] && (
+
+
+ 一键翻译
+
+ )} */}
+
+ {query.data && }
+
+
+ navigate("/insights")}>查看分析结果
+
+ >
+ )
+}
+
+export default ArticlesScreen
diff --git a/client/web/src/components/screen/insights.jsx b/client/web/src/components/screen/insights.jsx
new file mode 100644
index 0000000..90da40f
--- /dev/null
+++ b/client/web/src/components/screen/insights.jsx
@@ -0,0 +1,160 @@
+import { useEffect } from "react"
+import { useLocation } from "wouter"
+import { useMutation, useQueryClient } from "@tanstack/react-query"
+import { Files } from "lucide-react"
+import { ArticleList } from "@/components/article-list"
+import { Button } from "@/components/ui/button"
+import { Toaster } from "@/components/ui/toaster"
+import { ButtonLoading } from "@/components/ui/button-loading"
+import { useToast } from "@/components/ui/use-toast"
+import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
+import { useClientStore, useInsights, unlinkArticle, useInsightDates, useDatePager, more } from "@/store"
+
+function List({ insights, selected, onOpen, onDelete, onReport, onMore, isGettingMore, error }) {
+ function change(value) {
+ if (value) onOpen(value)
+ }
+
+ function unlink(article_id) {
+ onDelete(selected, article_id)
+ }
+
+ return (
+
+ {insights.map((insight, i) => (
+
+
+
+ {selected === insight.id &&
}
+
{insight.content}
+
+
+ x {insight.expand.articles.length}
+
+
+
+
+
+ {error && {error.message}
}
+
+ {(isGettingMore && ) || (
+
+
+ 生成报告
+
+
+ 搜索更多
+
+
+ )}
+
+
+ ))}
+
+ )
+}
+
+function InsightsScreen({}) {
+ const selectedInsight = useClientStore((state) => state.selectedInsight)
+ const selectInsight = useClientStore((state) => state.selectInsight)
+ const dates = useInsightDates()
+ const { index, last, next, hasLast, hasNext } = useDatePager(dates)
+ // console.log(dates, index)
+ const currentDate = dates.length > 0 && index >= 0 ? dates[index] : ""
+ const data = useInsights(currentDate)
+ // console.log(data)
+ const [, navigate] = useLocation()
+ const queryClient = useQueryClient()
+ const mut = useMutation({
+ mutationFn: (data) => {
+ if (data && selectInsight && data.find((insight) => insight.id == selectedInsight).expand.articles.length == 1) {
+ throw new Error("不能删除最后一篇文章")
+ }
+ return unlinkArticle(data)
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ["insights", currentDate] })
+ },
+ })
+
+ const mutMore = useMutation({
+ mutationFn: (data) => {
+ return more(data)
+ },
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ["insights", currentDate] })
+ },
+ })
+
+ const { toast } = useToast()
+ const queryCache = queryClient.getQueryCache()
+ queryCache.onError = (error) => {
+ console.log("error in cache", error)
+ toast({
+ variant: "destructive",
+ title: "出错啦!",
+ description: error.message,
+ })
+ }
+
+ useEffect(() => {
+ selectInsight(null)
+ }, [index])
+
+ useEffect(() => {
+ mut.reset() // only show error with the selected insight
+ }, [selectedInsight])
+
+ function unlink(insight_id, article_id) {
+ mut.mutate({ insight_id, article_id })
+ }
+
+ function report() {
+ navigate("/report/" + selectedInsight)
+ }
+
+ function getMore() {
+ console.log()
+ mutMore.mutate({ insight_id: selectedInsight })
+ }
+
+ return (
+ <>
+ 分析结果
+ {currentDate && (
+
+
+ <
+
+
{currentDate}
+
+ >
+
+
+ )}
+ {data && (
+
+
+
+
+ selectInsight(id)} onDelete={unlink} onReport={report} onMore={getMore} isGettingMore={mutMore.isPending} error={mut.error} />
+
+
共{Object.keys(data).length}条结果
+
+
+ )}
+
+ >
+ )
+}
+
+export default InsightsScreen
diff --git a/client/web/src/components/screen/login.jsx b/client/web/src/components/screen/login.jsx
new file mode 100644
index 0000000..3daf1c3
--- /dev/null
+++ b/client/web/src/components/screen/login.jsx
@@ -0,0 +1,82 @@
+// import { zodResolver } from '@hookform/resolvers/zod'
+import { useForm } from 'react-hook-form'
+// import * as z from 'zod'
+import { useMutation } from '@tanstack/react-query'
+
+import { Button } from '@/components/ui/button'
+import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
+import { Input } from '@/components/ui/input'
+
+import { useLocation } from 'wouter'
+import { login } from '@/store'
+
+// const FormSchema = z.object({
+// username: z.string().nonempty('请填写用户名'),
+// password: z.string().nonempty('请填写密码'),
+// })
+
+export function AdminLoginScreen() {
+ const form = useForm({
+ // resolver: zodResolver(FormSchema),
+ defaultValues: {
+ username: '',
+ password: '',
+ },
+ })
+
+ const [, setLocation] = useLocation()
+ const mutation = useMutation({
+ mutationFn: login,
+ onSuccess: (data) => {
+ setLocation('/')
+ },
+ })
+
+ function onSubmit(e) {
+ mutation.mutate({ username: form.getValues('username'), password: form.getValues('password') })
+ }
+
+ return (
+
+ )
+}
+
+export default AdminLoginScreen
diff --git a/client/web/src/components/screen/report.jsx b/client/web/src/components/screen/report.jsx
new file mode 100644
index 0000000..6ba4f52
--- /dev/null
+++ b/client/web/src/components/screen/report.jsx
@@ -0,0 +1,98 @@
+import { useMutation, useQueryClient } from "@tanstack/react-query"
+import { Button } from "@/components/ui/button"
+import { Textarea } from "@/components/ui/textarea"
+import { Input } from "@/components/ui/input"
+import { ButtonLoading } from "@/components/ui/button-loading"
+import { FileDown } from "lucide-react"
+import { useClientStore, report, useInsight } from "@/store"
+import { useEffect } from "react"
+import { useLocation, useParams } from "wouter"
+
+function ReportScreen({}) {
+ // const selectedInsight = useClientStore((state) => state.selectedInsight)
+ // const workflow_name = useClientStore((state) => state.workflow_name)
+ // const taskId = useClientStore((state) => state.taskId)
+ // const [wasWorking, setWasWorking] = useState(false)
+
+ const toc = useClientStore((state) => state.toc)
+ const updateToc = useClientStore((state) => state.updateToc)
+ const comment = useClientStore((state) => state.comment)
+ const updateComment = useClientStore((state) => state.updateComment)
+
+ const [, navigate] = useLocation()
+ const params = useParams()
+
+ useEffect(() => {
+ if (!params || !params.insight_id) {
+ console.log("expect /report/[insight_id]")
+ navigate("/insights", { replace: true })
+ }
+ }, [])
+
+ const query = useInsight(params.insight_id)
+ const queryClient = useQueryClient()
+
+ const mut = useMutation({
+ mutationFn: async (data) => report(data),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ["insight", params.insight_id] })
+ },
+ })
+
+ function changeToc(e) {
+ let lines = e.target.value.split("\n")
+ if (lines.length == 1 && lines[0] == "") lines = []
+ // updateToc(lines.filter((l) => l.trim()))
+ updateToc(lines)
+ }
+
+ function changeComment(e) {
+ updateComment(e.target.value)
+ }
+
+ function submit(e) {
+ mut.mutate({ toc: toc, insight_id: params.insight_id, comment: comment })
+ }
+
+ return (
+ <>
+
+
已选择分析结果:
+ {query.data &&
{query.data.content}
}
+
+
+
报告大纲:
+
+ 首行输入标题,每个纲目或章节单独一行. 首行空白自动生成标题.
+ {query.data?.docx && }
+
+
+ {(mut.isPending && ) || (
+
+ {query.data?.docx ? "再次生成" : "生成"}
+
+ )}
+ {!mut.isPending && (
+ navigate("/insights")}>
+ 选择其他分析结果
+
+ )}
+
+ {!mut.isPending && query.data?.docx && (
+
+ )}
+ {query.isError && {query.error.message}
}
+ {mut.isError && {mut.error.message}
}
+ >
+ )
+}
+
+export default ReportScreen
diff --git a/client/web/src/components/screen/start.jsx b/client/web/src/components/screen/start.jsx
new file mode 100644
index 0000000..982c743
--- /dev/null
+++ b/client/web/src/components/screen/start.jsx
@@ -0,0 +1,58 @@
+import { Textarea } from "@/components/ui/textarea"
+import { Label } from "@/components/ui/label"
+import { Button } from "@/components/ui/button"
+import { ButtonLoading } from "@/components/ui/button-loading"
+import { useMutation } from "@tanstack/react-query"
+import { Minus, Plus, Loader2 } from "lucide-react"
+import { useClientStore, createTask } from "@/store"
+
+function StartScreen({ navigate, id }) {
+ const s = useClientStore()
+ const mut = useMutation({
+ mutationFn: (data) => createTask(data),
+ onSuccess: () => {
+ //query.invalidate()
+ navigate("/articles")
+ },
+ })
+
+ function change(e) {
+ let urls = e.target.value.split("\n")
+ if (urls.length == 1 && urls[0] == "") urls = []
+ s.setUrls(urls)
+ }
+
+ function submit() {
+ mut.mutate({ urls: s.urls, days: s.days })
+ }
+
+ return (
+ <>
+
+
网站清单
+
+ {s.countUrls() > 0 &&
共{s.countUrls()}个网站
}
+
+ 仅抓取
+
+
+
+
{s.days}
+
+
+
+ 天内更新的文章
+
+
+ {mut.isError && {mut.error.message}
}
+ {(mut.isPending && ) || (
+
+ {mut.isLoading && }
+ 提交
+
+ )}
+ >
+ )
+}
+
+export default StartScreen
diff --git a/client/web/src/components/screen/steps.jsx b/client/web/src/components/screen/steps.jsx
new file mode 100644
index 0000000..2a4b026
--- /dev/null
+++ b/client/web/src/components/screen/steps.jsx
@@ -0,0 +1,105 @@
+import { useState, useTransition } from "react"
+import { Banner } from "@/components/ui/banner"
+import StepLayout from "@/components/layout/step"
+import StartScreen from "@/components/screen/start"
+import ArticlesScreen from "@/components/screen/articles"
+import InsightsScreen from "@/components/screen/insights"
+import ReportScreen from "@/components/screen/report"
+
+import { Loader2 } from "lucide-react"
+import { useEffect } from "react"
+import { useClientStore, useData } from "@/store"
+
+const TITLE = "情报分析"
+
+function Steps() {
+ let [currentScreen, setCurrentScreen] = useState("/insights")
+ const [isPending, startTransition] = useTransition()
+ const selectInsight = useClientStore((state) => state.selectInsight)
+ const selectedInsight = useClientStore((state) => state.selectedInsight)
+ const taskId = useClientStore((state) => state.taskId)
+ const setTaskId = useClientStore((state) => state.setTaskId)
+
+ // useEffect(() => {
+ // const searchParams = new URLSearchParams(document.location.search)
+ // let taskIdSpecified = searchParams.get("task_id")
+ // if (taskIdSpecified) {
+ // setTaskId(taskIdSpecified)
+ // }
+ // }, [])
+
+ // const query = useData(taskId)
+ // console.log(taskId, query.data)
+
+ // useEffect(() => {
+ // // navigate away from /start
+ // if (query.data && currentScreen == "/start") {
+ // let state = query.data
+ // if (state.articles && Object.keys(state.articles).length > 0) {
+ // setCurrentScreen("/articles")
+ // }
+
+ // if (state.insights && Object.keys(state.insights).length > 0) {
+ // if (selectedInsight && state.insights[selectedInsight]?.report?.file) {
+ // setCurrentScreen("/report")
+ // } else {
+ // setCurrentScreen("/insights")
+ // }
+ // } else {
+ // selectInsight(null) // deselect
+ // }
+ // }
+ // }, [query.data])
+
+ // const errors = (query.isError && [query.error]) || (query.data && query.data.errors && query.data.errors.length > 0 && query.data.errors)
+
+ function navigate(screen) {
+ startTransition(() => {
+ setCurrentScreen(screen)
+ })
+ }
+
+ // console.log("screen:", currenScreen)
+
+ let content, title
+ if (currentScreen == "/start") {
+ title = TITLE + " > " + "数据来源"
+ content =
+ } else if (currentScreen == "/articles") {
+ title = TITLE + " > " + "文章列表"
+ content =
+ } else if (currentScreen == "/insights") {
+ title = TITLE + " > " + "分析结果"
+ content =
+ } else if (currentScreen == "/report") {
+ title = TITLE + " > " + "生成报告"
+ content =
+ }
+
+ return (
+
+ {content}
+ {/* {errors && (
+
+ {errors.map((e, i) => (
+ {e}
+ ))}
+
+ )} */}
+
+ {/* {query.data && query.data.working && (
+
+
+
+ )} */}
+ {/* {query.isFetching && (
+
+
+
+ )} */}
+ {/* task_id:{taskId}
*/}
+
+ )
+}
+
+export default Steps
diff --git a/client/web/src/components/ui/accordion.jsx b/client/web/src/components/ui/accordion.jsx
new file mode 100644
index 0000000..1f8e5ce
--- /dev/null
+++ b/client/web/src/components/ui/accordion.jsx
@@ -0,0 +1,41 @@
+import * as React from "react"
+import * as AccordionPrimitive from "@radix-ui/react-accordion"
+import { ChevronDown } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+const Accordion = AccordionPrimitive.Root
+
+const AccordionItem = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+AccordionItem.displayName = "AccordionItem"
+
+const AccordionTrigger = React.forwardRef(({ className, children, ...props }, ref) => (
+
+ svg]:rotate-180",
+ className
+ )}
+ {...props}>
+ {children}
+
+
+
+))
+AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
+
+const AccordionContent = React.forwardRef(({ className, children, ...props }, ref) => (
+
+ {children}
+
+))
+
+AccordionContent.displayName = AccordionPrimitive.Content.displayName
+
+export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
diff --git a/client/web/src/components/ui/banner.jsx b/client/web/src/components/ui/banner.jsx
new file mode 100644
index 0000000..75c11d0
--- /dev/null
+++ b/client/web/src/components/ui/banner.jsx
@@ -0,0 +1,9 @@
+import * as React from "react"
+import { cn } from "@/lib/utils"
+
+const Banner = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+Banner.displayName = "Banner"
+
+export { Banner }
diff --git a/client/web/src/components/ui/button-loading.jsx b/client/web/src/components/ui/button-loading.jsx
new file mode 100644
index 0000000..69994d1
--- /dev/null
+++ b/client/web/src/components/ui/button-loading.jsx
@@ -0,0 +1,11 @@
+import { Button } from '@/components/ui/button'
+import { Loader2 } from 'lucide-react'
+
+export function ButtonLoading() {
+ return (
+
+
+ 请稍后
+
+ )
+}
diff --git a/client/web/src/components/ui/button.jsx b/client/web/src/components/ui/button.jsx
new file mode 100644
index 0000000..9bdf65b
--- /dev/null
+++ b/client/web/src/components/ui/button.jsx
@@ -0,0 +1,47 @@
+import * as React from "react"
+import { Slot } from "@radix-ui/react-slot"
+import { cva } from "class-variance-authority";
+
+import { cn } from "@/lib/utils"
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-destructive-foreground hover:bg-destructive/90",
+ outline:
+ "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
+ secondary:
+ "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default: "h-10 px-4 py-2",
+ sm: "h-9 rounded-md px-3",
+ lg: "h-11 rounded-md px-8",
+ icon: "h-10 w-10",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+)
+
+const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : "button"
+ return (
+ ( )
+ );
+})
+Button.displayName = "Button"
+
+export { Button, buttonVariants }
diff --git a/client/web/src/components/ui/form.jsx b/client/web/src/components/ui/form.jsx
new file mode 100644
index 0000000..5275c62
--- /dev/null
+++ b/client/web/src/components/ui/form.jsx
@@ -0,0 +1,133 @@
+import * as React from "react"
+import { Slot } from "@radix-ui/react-slot"
+import { Controller, FormProvider, useFormContext } from "react-hook-form";
+
+import { cn } from "@/lib/utils"
+import { Label } from "@/components/ui/label"
+
+const Form = FormProvider
+
+const FormFieldContext = React.createContext({})
+
+const FormField = (
+ {
+ ...props
+ }
+) => {
+ return (
+ (
+
+ )
+ );
+}
+
+const useFormField = () => {
+ const fieldContext = React.useContext(FormFieldContext)
+ const itemContext = React.useContext(FormItemContext)
+ const { getFieldState, formState } = useFormContext()
+
+ const fieldState = getFieldState(fieldContext.name, formState)
+
+ if (!fieldContext) {
+ throw new Error("useFormField should be used within ")
+ }
+
+ const { id } = itemContext
+
+ return {
+ id,
+ name: fieldContext.name,
+ formItemId: `${id}-form-item`,
+ formDescriptionId: `${id}-form-item-description`,
+ formMessageId: `${id}-form-item-message`,
+ ...fieldState,
+ }
+}
+
+const FormItemContext = React.createContext({})
+
+const FormItem = React.forwardRef(({ className, ...props }, ref) => {
+ const id = React.useId()
+
+ return (
+ (
+
+ )
+ );
+})
+FormItem.displayName = "FormItem"
+
+const FormLabel = React.forwardRef(({ className, ...props }, ref) => {
+ const { error, formItemId } = useFormField()
+
+ return (
+ ( )
+ );
+})
+FormLabel.displayName = "FormLabel"
+
+const FormControl = React.forwardRef(({ ...props }, ref) => {
+ const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
+
+ return (
+ ( )
+ );
+})
+FormControl.displayName = "FormControl"
+
+const FormDescription = React.forwardRef(({ className, ...props }, ref) => {
+ const { formDescriptionId } = useFormField()
+
+ return (
+ (
)
+ );
+})
+FormDescription.displayName = "FormDescription"
+
+const FormMessage = React.forwardRef(({ className, children, ...props }, ref) => {
+ const { error, formMessageId } = useFormField()
+ const body = error ? String(error?.message) : children
+
+ if (!body) {
+ return null
+ }
+
+ return (
+ (
+ {body}
+
)
+ );
+})
+FormMessage.displayName = "FormMessage"
+
+export {
+ useFormField,
+ Form,
+ FormItem,
+ FormLabel,
+ FormControl,
+ FormDescription,
+ FormMessage,
+ FormField,
+}
diff --git a/client/web/src/components/ui/input.jsx b/client/web/src/components/ui/input.jsx
new file mode 100644
index 0000000..c74d919
--- /dev/null
+++ b/client/web/src/components/ui/input.jsx
@@ -0,0 +1,19 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Input = React.forwardRef(({ className, type, ...props }, ref) => {
+ return (
+ ( )
+ );
+})
+Input.displayName = "Input"
+
+export { Input }
diff --git a/client/web/src/components/ui/label.jsx b/client/web/src/components/ui/label.jsx
new file mode 100644
index 0000000..a1f4099
--- /dev/null
+++ b/client/web/src/components/ui/label.jsx
@@ -0,0 +1,16 @@
+import * as React from "react"
+import * as LabelPrimitive from "@radix-ui/react-label"
+import { cva } from "class-variance-authority";
+
+import { cn } from "@/lib/utils"
+
+const labelVariants = cva(
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
+)
+
+const Label = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+Label.displayName = LabelPrimitive.Root.displayName
+
+export { Label }
diff --git a/client/web/src/components/ui/textarea.jsx b/client/web/src/components/ui/textarea.jsx
new file mode 100644
index 0000000..7369cf5
--- /dev/null
+++ b/client/web/src/components/ui/textarea.jsx
@@ -0,0 +1,18 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Textarea = React.forwardRef(({ className, ...props }, ref) => {
+ return (
+ ()
+ );
+})
+Textarea.displayName = "Textarea"
+
+export { Textarea }
diff --git a/client/web/src/components/ui/toast.jsx b/client/web/src/components/ui/toast.jsx
new file mode 100644
index 0000000..c95bc40
--- /dev/null
+++ b/client/web/src/components/ui/toast.jsx
@@ -0,0 +1,82 @@
+import * as React from "react"
+import * as ToastPrimitives from "@radix-ui/react-toast"
+import { cva } from "class-variance-authority";
+import { X } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+const ToastProvider = ToastPrimitives.Provider
+
+const ToastViewport = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+ToastViewport.displayName = ToastPrimitives.Viewport.displayName
+
+const toastVariants = cva(
+ "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
+ {
+ variants: {
+ variant: {
+ default: "border bg-background text-foreground",
+ destructive:
+ "destructive group border-destructive bg-destructive text-destructive-foreground",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ }
+)
+
+const Toast = React.forwardRef(({ className, variant, ...props }, ref) => {
+ return (
+ ( )
+ );
+})
+Toast.displayName = ToastPrimitives.Root.displayName
+
+const ToastAction = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+ToastAction.displayName = ToastPrimitives.Action.displayName
+
+const ToastClose = React.forwardRef(({ className, ...props }, ref) => (
+
+
+
+))
+ToastClose.displayName = ToastPrimitives.Close.displayName
+
+const ToastTitle = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+ToastTitle.displayName = ToastPrimitives.Title.displayName
+
+const ToastDescription = React.forwardRef(({ className, ...props }, ref) => (
+
+))
+ToastDescription.displayName = ToastPrimitives.Description.displayName
+
+export { ToastProvider, ToastViewport, Toast, ToastTitle, ToastDescription, ToastClose, ToastAction };
diff --git a/client/web/src/components/ui/toaster.jsx b/client/web/src/components/ui/toaster.jsx
new file mode 100644
index 0000000..b7a9a25
--- /dev/null
+++ b/client/web/src/components/ui/toaster.jsx
@@ -0,0 +1,33 @@
+import {
+ Toast,
+ ToastClose,
+ ToastDescription,
+ ToastProvider,
+ ToastTitle,
+ ToastViewport,
+} from "@/components/ui/toast"
+import { useToast } from "@/components/ui/use-toast"
+
+export function Toaster() {
+ const { toasts } = useToast()
+
+ return (
+ (
+ {toasts.map(function ({ id, title, description, action, ...props }) {
+ return (
+ (
+
+ {title && {title} }
+ {description && (
+ {description}
+ )}
+
+ {action}
+
+ )
+ );
+ })}
+
+ )
+ );
+}
diff --git a/client/web/src/components/ui/use-toast.js b/client/web/src/components/ui/use-toast.js
new file mode 100644
index 0000000..df6b786
--- /dev/null
+++ b/client/web/src/components/ui/use-toast.js
@@ -0,0 +1,154 @@
+// Inspired by react-hot-toast library
+import * as React from "react"
+
+const TOAST_LIMIT = 1
+const TOAST_REMOVE_DELAY = 1000000
+
+const actionTypes = {
+ ADD_TOAST: "ADD_TOAST",
+ UPDATE_TOAST: "UPDATE_TOAST",
+ DISMISS_TOAST: "DISMISS_TOAST",
+ REMOVE_TOAST: "REMOVE_TOAST"
+}
+
+let count = 0
+
+function genId() {
+ count = (count + 1) % Number.MAX_SAFE_INTEGER
+ return count.toString();
+}
+
+const toastTimeouts = new Map()
+
+const addToRemoveQueue = (toastId) => {
+ if (toastTimeouts.has(toastId)) {
+ return
+ }
+
+ const timeout = setTimeout(() => {
+ toastTimeouts.delete(toastId)
+ dispatch({
+ type: "REMOVE_TOAST",
+ toastId: toastId,
+ })
+ }, TOAST_REMOVE_DELAY)
+
+ toastTimeouts.set(toastId, timeout)
+}
+
+export const reducer = (state, action) => {
+ switch (action.type) {
+ case "ADD_TOAST":
+ return {
+ ...state,
+ toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
+ };
+
+ case "UPDATE_TOAST":
+ return {
+ ...state,
+ toasts: state.toasts.map((t) =>
+ t.id === action.toast.id ? { ...t, ...action.toast } : t),
+ };
+
+ case "DISMISS_TOAST": {
+ const { toastId } = action
+
+ // ! Side effects ! - This could be extracted into a dismissToast() action,
+ // but I'll keep it here for simplicity
+ if (toastId) {
+ addToRemoveQueue(toastId)
+ } else {
+ state.toasts.forEach((toast) => {
+ addToRemoveQueue(toast.id)
+ })
+ }
+
+ return {
+ ...state,
+ toasts: state.toasts.map((t) =>
+ t.id === toastId || toastId === undefined
+ ? {
+ ...t,
+ open: false,
+ }
+ : t),
+ };
+ }
+ case "REMOVE_TOAST":
+ if (action.toastId === undefined) {
+ return {
+ ...state,
+ toasts: [],
+ }
+ }
+ return {
+ ...state,
+ toasts: state.toasts.filter((t) => t.id !== action.toastId),
+ };
+ }
+}
+
+const listeners = []
+
+let memoryState = { toasts: [] }
+
+function dispatch(action) {
+ memoryState = reducer(memoryState, action)
+ listeners.forEach((listener) => {
+ listener(memoryState)
+ })
+}
+
+function toast({
+ ...props
+}) {
+ const id = genId()
+
+ const update = (props) =>
+ dispatch({
+ type: "UPDATE_TOAST",
+ toast: { ...props, id },
+ })
+ const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
+
+ dispatch({
+ type: "ADD_TOAST",
+ toast: {
+ ...props,
+ id,
+ open: true,
+ onOpenChange: (open) => {
+ if (!open) dismiss()
+ },
+ },
+ })
+
+ return {
+ id: id,
+ dismiss,
+ update,
+ }
+}
+
+function useToast() {
+ const [state, setState] = React.useState(memoryState)
+
+ React.useEffect(() => {
+ listeners.push(setState)
+ return () => {
+ const index = listeners.indexOf(setState)
+ if (index > -1) {
+ listeners.splice(index, 1)
+ }
+ };
+ }, [state])
+
+ return {
+ ...state,
+ toast,
+ dismiss: (toastId) => dispatch({ type: "DISMISS_TOAST", toastId }),
+ };
+}
+
+export { useToast, toast }
diff --git a/client/web/src/index.css b/client/web/src/index.css
new file mode 100644
index 0000000..b55d994
--- /dev/null
+++ b/client/web/src/index.css
@@ -0,0 +1,82 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ :root {
+ --background: 0 0% 100%;
+ --foreground: 222.2 84% 4.9%;
+
+ --card: 0 0% 100%;
+ --card-foreground: 222.2 84% 4.9%;
+
+ --popover: 0 0% 100%;
+ --popover-foreground: 222.2 84% 4.9%;
+
+ --primary: 222.2 47.4% 11.2%;
+ --primary-foreground: 210 40% 98%;
+
+ --secondary: 210 40% 96.1%;
+ --secondary-foreground: 222.2 47.4% 11.2%;
+
+ --muted: 210 40% 96.1%;
+ --muted-foreground: 215.4 16.3% 46.9%;
+
+ --accent: 210 40% 96.1%;
+ --accent-foreground: 222.2 47.4% 11.2%;
+
+ --destructive: 0 84.2% 60.2%;
+ --destructive-foreground: 210 40% 98%;
+
+ --border: 214.3 31.8% 91.4%;
+ --input: 214.3 31.8% 91.4%;
+ --ring: 222.2 84% 4.9%;
+
+ --radius: 0.5rem;
+ }
+
+ .dark {
+ --background: 222.2 84% 4.9%;
+ --foreground: 210 40% 98%;
+
+ --card: 222.2 84% 4.9%;
+ --card-foreground: 210 40% 98%;
+
+ --popover: 222.2 84% 4.9%;
+ --popover-foreground: 210 40% 98%;
+
+ --primary: 210 40% 98%;
+ --primary-foreground: 222.2 47.4% 11.2%;
+
+ --secondary: 217.2 32.6% 17.5%;
+ --secondary-foreground: 210 40% 98%;
+
+ --muted: 217.2 32.6% 17.5%;
+ --muted-foreground: 215 20.2% 65.1%;
+
+ --accent: 217.2 32.6% 17.5%;
+ --accent-foreground: 210 40% 98%;
+
+ --destructive: 0 62.8% 30.6%;
+ --destructive-foreground: 210 40% 98%;
+
+ --border: 217.2 32.6% 17.5%;
+ --input: 217.2 32.6% 17.5%;
+ --ring: 212.7 26.8% 83.9%;
+ }
+}
+
+@layer base {
+ * {
+ @apply border-border;
+ }
+ body {
+ @apply bg-background text-foreground;
+ }
+}
+
+@layer components {
+ h2 {
+ @apply scroll-m-20 text-2xl font-semibold tracking-tight mb-4;
+ }
+}
diff --git a/client/web/src/lib/utils.js b/client/web/src/lib/utils.js
new file mode 100644
index 0000000..d314d8c
--- /dev/null
+++ b/client/web/src/lib/utils.js
@@ -0,0 +1,18 @@
+import { clsx } from "clsx"
+import { twMerge } from "tailwind-merge"
+
+export function cn(...inputs) {
+ return twMerge(clsx(inputs))
+}
+
+export function formatDate(date) {
+ var d = new Date(isNaN(date) ? date + "T00:00:00" : date)
+ var iso = d.toISOString()
+ return iso.slice(0, 10) + " " + iso.slice(11, 23) + "Z"
+ // return [d.getFullYear(), (d.getMonth() + 1).padLeft(), d.getDate().padLeft()].join("-") + " " + [d.getHours().padLeft(), d.getMinutes().padLeft(), d.getSeconds().padLeft()].join(":") + ".000Z"
+}
+
+Number.prototype.padLeft = function (base, chr) {
+ var len = String(base || 10).length - String(this).length + 1
+ return len > 0 ? new Array(len).join(chr || "0") + this : this
+}
diff --git a/client/web/src/main.jsx b/client/web/src/main.jsx
new file mode 100644
index 0000000..54b39dd
--- /dev/null
+++ b/client/web/src/main.jsx
@@ -0,0 +1,10 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App.jsx'
+import './index.css'
+
+ReactDOM.createRoot(document.getElementById('root')).render(
+
+
+ ,
+)
diff --git a/client/web/src/store.js b/client/web/src/store.js
new file mode 100644
index 0000000..be5fb65
--- /dev/null
+++ b/client/web/src/store.js
@@ -0,0 +1,273 @@
+import { useEffect, useState } from "react"
+import PocketBase from "pocketbase"
+const pb = new PocketBase(import.meta.env.VITE_PB_BASE)
+import { useQuery } from "@tanstack/react-query"
+
+import { create } from "zustand"
+import { persist } from "zustand/middleware"
+// import axios from "redaxios"
+import axios from "axios"
+import { nanoid } from "nanoid"
+
+import { formatDate } from "./lib/utils"
+
+const DAYS_RANGE = [1, 14]
+
+export const useClientStore = create(
+ persist(
+ (set, get) => ({
+ taskId: "",
+ urls: ["https://cyberscoop.com"],
+ days: 14,
+ workflow_name: "情报分析",
+ toc: ["参考情报", "基本内容", "相关发声情况", "应对策略"],
+ selectedInsight: null,
+ comment: "",
+
+ setTaskId: (taskId) => set({ taskId }),
+ setUrls: (urls) => set({ urls }),
+ countUrls: () => get().urls.filter((url) => url).length,
+ selectInsight: (id) => set({ selectedInsight: id }),
+ updateToc: (value) => set({ toc: value }),
+ updateComment: (value) => set({ comment: value }),
+ incr: () => set((state) => ({ days: state.days + 1 > DAYS_RANGE[1] ? DAYS_RANGE[1] : state.days + 1 })),
+ decr: () => set((state) => ({ days: state.days - 1 < DAYS_RANGE[0] ? DAYS_RANGE[0] : state.days - 1 })),
+ minDays: () => get().days === DAYS_RANGE[0],
+ maxDays: () => get().days === DAYS_RANGE[1],
+ }),
+ {
+ version: "0.1.1",
+ name: "aw-storage",
+ // storage: createJSONStorage(() => sessionStorage), // (optional) by default, 'localStorage' is used
+ }
+ )
+)
+
+export function login({ username, password }) {
+ //return pb.collection("users").authWithPassword(username, password)
+ return pb.admins.authWithPassword(username, password)
+}
+
+export function isAuth() {
+ return pb.authStore.isValid
+}
+
+export function useData(task_id, autoRefetch = undefined) {
+ let interval = parseInt(autoRefetch) >= 1000 ? parseInt(autoRefetch) : undefined
+
+ return useQuery({
+ queryKey: ["data", task_id ? task_id : ""],
+ queryFn: () => data(task_id ? task_id : ""),
+ refetchInterval: (query) => {
+ //console.log(query)
+ if (!query.state.data || (query.state.data && query.state.data.working)) {
+ return interval
+ }
+ return undefined
+ },
+ })
+}
+
+export function createTask({ id, urls, days }) {
+ let from = new Date()
+ from.setHours(0, 0, 0, 0)
+ from.setDate(from.getDate() - days)
+
+ let fromStr = from.toISOString().slice(0, 10).split("-").join("")
+ let task_id = id || nanoid(10)
+ console.log("creating task: ", task_id, urls.filter((url) => url).length + " sites", fromStr)
+
+ if (urls.length == 0) {
+ urls.push("")
+ }
+
+ return axios({
+ method: "post",
+ url: `${import.meta.env.VITE_API_BASE}/sites`,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ data: {
+ after: fromStr,
+ sites: urls,
+ task_id: task_id,
+ },
+ })
+ .then(function (response) {
+ useClientStore.getState().setTaskId(task_id)
+ return response
+ })
+ .catch(function (error) {
+ useClientStore.getState().setTaskId("")
+ return error
+ })
+}
+
+export function report({ task_id, insight_id, toc, comment }) {
+ return axios({
+ method: "post",
+ url: `${import.meta.env.VITE_API_BASE}/report`,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ data: {
+ task_id: task_id,
+ toc: toc,
+ insight_id: insight_id,
+ comment: comment,
+ },
+ })
+}
+
+export function more({ insight_id }) {
+ return axios({
+ method: "post",
+ url: `${import.meta.env.VITE_API_BASE}/search_for_insight`,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ data: {
+ //toc: toc,
+ insight_id: insight_id,
+ //comment: comment,
+ },
+ })
+}
+
+export function translations({ article_ids }) {
+ return axios({
+ method: "post",
+ url: `${import.meta.env.VITE_API_BASE}/translations`,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ data: {
+ article_ids,
+ },
+ })
+}
+
+export function useArticles(date) {
+ return useQuery({
+ queryKey: ["articles", date],
+ queryFn: () => getArticles(date),
+ })
+}
+
+export function useInsight(id) {
+ return useQuery({
+ queryKey: ["insight", id],
+ queryFn: () => getInsight(id),
+ })
+}
+
+export function useInsights(date) {
+ const { data = [] } = useQuery({
+ queryKey: ["insights", date],
+ queryFn: () => getInsights(date),
+ })
+ return data
+}
+
+export function useInsightDates() {
+ const { data = [] } = useQuery({
+ queryKey: ["insight_dates"],
+ queryFn: getInsightDates,
+ })
+ return data
+}
+
+export function useArticleDates() {
+ return useQuery({
+ queryKey: ["article_dates"],
+ queryFn: () => getArticleDates(),
+ })
+}
+
+export function useDatePager(dates) {
+ const [index, setIndex] = useState(-1)
+
+ useEffect(() => {
+ if (index < 0 && dates) {
+ setIndex(dates.length - 1)
+ }
+ }, [index, dates])
+
+ const hasLast = () => index > 0
+ const hasNext = () => index >= 0 && index < dates.length - 1
+ const last = () => hasLast() && setIndex(index - 1)
+ const next = () => hasNext() && setIndex(index + 1)
+
+ return {
+ index,
+ last,
+ next,
+ hasLast,
+ hasNext,
+ }
+}
+
+export function getArticles(date) {
+ if (!date) return []
+
+ const from = formatDate(date)
+ const to = formatDate(new Date(new Date(date).getTime() + 60 * 60 * 24 * 1000))
+ return pb.collection("articles").getFullList({
+ sort: "-created",
+ expand: "translation_result",
+ filter: 'created >= "' + from + '" && created < "' + to + '"',
+ })
+}
+
+export function getInsight(id) {
+ return pb.collection("insights").getOne(id, { expand: "docx" })
+}
+
+export function getInsights(date) {
+ if (!date) return null
+
+ const from = formatDate(date)
+ const to = formatDate(new Date(new Date(date + "T00:00:00").getTime() + 60 * 60 * 24 * 1000))
+ // console.log("from/to", from, to)
+
+ const f = 'created >= "' + from + '" && created < "' + to + '"'
+ console.log(f)
+
+ return pb.collection("insights").getFullList({
+ sort: "-created",
+ expand: "articles, articles.translation_result",
+ // expand: "articles",
+ filter: f,
+ })
+}
+
+export async function getInsightDates() {
+ const { data } = await axios({
+ method: "get",
+ url: `${import.meta.env.VITE_PB_BASE}/insight_dates`,
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer " + pb.authStore?.token,
+ },
+ })
+ // return data.map((d) => new Date(d + "T00:00:00Z").toLocaleDateString().split("/").join("-"))
+ return data
+}
+
+export async function getArticleDates() {
+ let { data } = await axios({
+ method: "get",
+ url: `${import.meta.env.VITE_PB_BASE}/article_dates`,
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer " + pb.authStore?.token,
+ },
+ })
+ return data
+}
+
+export function unlinkArticle({ insight_id, article_id }) {
+ return pb.collection("insights").update(insight_id, {
+ "articles-": article_id,
+ })
+}
diff --git a/client/web/tailwind.config.js b/client/web/tailwind.config.js
new file mode 100644
index 0000000..0a5fa43
--- /dev/null
+++ b/client/web/tailwind.config.js
@@ -0,0 +1,77 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ darkMode: ["class"],
+ content: [
+ './pages/**/*.{js,jsx}',
+ './components/**/*.{js,jsx}',
+ './app/**/*.{js,jsx}',
+ './src/**/*.{js,jsx}',
+ ],
+ prefix: "",
+ theme: {
+ container: {
+ center: true,
+ padding: "2rem",
+ screens: {
+ "2xl": "1400px",
+ },
+ },
+ extend: {
+ colors: {
+ border: "hsl(var(--border))",
+ input: "hsl(var(--input))",
+ ring: "hsl(var(--ring))",
+ background: "hsl(var(--background))",
+ foreground: "hsl(var(--foreground))",
+ primary: {
+ DEFAULT: "hsl(var(--primary))",
+ foreground: "hsl(var(--primary-foreground))",
+ },
+ secondary: {
+ DEFAULT: "hsl(var(--secondary))",
+ foreground: "hsl(var(--secondary-foreground))",
+ },
+ destructive: {
+ DEFAULT: "hsl(var(--destructive))",
+ foreground: "hsl(var(--destructive-foreground))",
+ },
+ muted: {
+ DEFAULT: "hsl(var(--muted))",
+ foreground: "hsl(var(--muted-foreground))",
+ },
+ accent: {
+ DEFAULT: "hsl(var(--accent))",
+ foreground: "hsl(var(--accent-foreground))",
+ },
+ popover: {
+ DEFAULT: "hsl(var(--popover))",
+ foreground: "hsl(var(--popover-foreground))",
+ },
+ card: {
+ DEFAULT: "hsl(var(--card))",
+ foreground: "hsl(var(--card-foreground))",
+ },
+ },
+ borderRadius: {
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)",
+ },
+ keyframes: {
+ "accordion-down": {
+ from: { height: "0" },
+ to: { height: "var(--radix-accordion-content-height)" },
+ },
+ "accordion-up": {
+ from: { height: "var(--radix-accordion-content-height)" },
+ to: { height: "0" },
+ },
+ },
+ animation: {
+ "accordion-down": "accordion-down 0.2s ease-out",
+ "accordion-up": "accordion-up 0.2s ease-out",
+ },
+ },
+ },
+ plugins: [require("tailwindcss-animate")],
+}
\ No newline at end of file
diff --git a/client/web/tsconfig.json b/client/web/tsconfig.json
new file mode 100644
index 0000000..abe04df
--- /dev/null
+++ b/client/web/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ }
+}
diff --git a/client/web/vite.config.js b/client/web/vite.config.js
new file mode 100644
index 0000000..86bd487
--- /dev/null
+++ b/client/web/vite.config.js
@@ -0,0 +1,15 @@
+import path from "path"
+import * as child from "child_process"
+import { defineConfig } from "vite"
+import react from "@vitejs/plugin-react"
+// const commitHash = child.execSync('git rev-parse --short HEAD').toString()
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ resolve: {
+ alias: {
+ "@": path.resolve(__dirname, "./src"),
+ },
+ },
+ // define: { 'import.meta.env.VITE_APP_VERSION': JSON.stringify(commitHash) },
+})
From e2d82eb7e8d02e0946f3f81a9cec77f72402e116 Mon Sep 17 00:00:00 2001
From: Lingfei Song <82314+madcat@users.noreply.github.com>
Date: Thu, 11 Apr 2024 12:53:18 +0700
Subject: [PATCH 07/16] report layout adjustments
---
client/web/src/components/screen/articles.jsx | 2 +-
client/web/src/components/screen/report.jsx | 15 ++++++++-------
client/web/src/index.css | 2 +-
3 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/client/web/src/components/screen/articles.jsx b/client/web/src/components/screen/articles.jsx
index 2c3045f..05323d9 100644
--- a/client/web/src/components/screen/articles.jsx
+++ b/client/web/src/components/screen/articles.jsx
@@ -27,7 +27,7 @@ function ArticlesScreen({}) {
})
function trans() {
- mut.mutate({ article_ids: query.data.map((d) => d.id) })
+ mut.mutate({ article_ids: query.data.filter((d) => !d.translation_result).map((d) => d.id) })
}
return (
diff --git a/client/web/src/components/screen/report.jsx b/client/web/src/components/screen/report.jsx
index 6ba4f52..44b9cec 100644
--- a/client/web/src/components/screen/report.jsx
+++ b/client/web/src/components/screen/report.jsx
@@ -55,18 +55,19 @@ function ReportScreen({}) {
}
return (
- <>
+
+
报告生成
已选择分析结果:
- {query.data &&
{query.data.content}
}
+ {query.data &&
{query.data.content}
}
报告大纲:
-
+
首行输入标题,每个纲目或章节单独一行. 首行空白自动生成标题.
- {query.data?.docx && }
+ {query.data?.docx && }
-
+
{(mut.isPending && ) || (
{query.data?.docx ? "再次生成" : "生成"}
@@ -79,7 +80,7 @@ function ReportScreen({}) {
)}
{!mut.isPending && query.data?.docx && (
-
+
报告已生成,点击下载
@@ -91,7 +92,7 @@ function ReportScreen({}) {
)}
{query.isError &&
{query.error.message}
}
{mut.isError &&
{mut.error.message}
}
- >
+
)
}
diff --git a/client/web/src/index.css b/client/web/src/index.css
index b55d994..cb11880 100644
--- a/client/web/src/index.css
+++ b/client/web/src/index.css
@@ -77,6 +77,6 @@
@layer components {
h2 {
- @apply scroll-m-20 text-2xl font-semibold tracking-tight mb-4;
+ @apply scroll-m-20 text-2xl font-semibold tracking-tight mb-4 text-left;
}
}
From fcae0138b74d4d3e92e06c02c5666739271073b6 Mon Sep 17 00:00:00 2001
From: Lingfei Song <82314+madcat@users.noreply.github.com>
Date: Fri, 12 Apr 2024 11:04:07 +0700
Subject: [PATCH 08/16] page data in utc yyyy-mm-dd, not local date
---
client/Dockerfile.web | 4 +++-
client/pb/pb_hooks/main.pb.js | 2 +-
client/web/src/components/screen/insights.jsx | 6 +++---
client/web/src/lib/utils.js | 5 ++++-
client/web/src/store.js | 15 +++++++++------
5 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/client/Dockerfile.web b/client/Dockerfile.web
index d4ef67d..df59a6b 100644
--- a/client/Dockerfile.web
+++ b/client/Dockerfile.web
@@ -12,7 +12,9 @@ FROM alpine:latest
ARG PB_VERSION=0.21.1
-RUN apk add --no-cache unzip ca-certificates tzdata
+RUN apk add --no-cache unzip ca-certificates tzdata && \
+ ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
+
# download and unzip PocketBase
ADD https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_linux_amd64.zip /tmp/pb.zip
diff --git a/client/pb/pb_hooks/main.pb.js b/client/pb/pb_hooks/main.pb.js
index 44bf76a..7f585e8 100644
--- a/client/pb/pb_hooks/main.pb.js
+++ b/client/pb/pb_hooks/main.pb.js
@@ -43,7 +43,7 @@ routerAdd(
})
)
- $app.dao().db().newQuery("SELECT DISTINCT DATE(created, 'localtime') as created FROM insights").all(result)
+ $app.dao().db().newQuery("SELECT DISTINCT DATE(created) as created FROM insights").all(result)
return c.json(
200,
diff --git a/client/web/src/components/screen/insights.jsx b/client/web/src/components/screen/insights.jsx
index 90da40f..2cbbd8c 100644
--- a/client/web/src/components/screen/insights.jsx
+++ b/client/web/src/components/screen/insights.jsx
@@ -66,11 +66,11 @@ function InsightsScreen({}) {
const [, navigate] = useLocation()
const queryClient = useQueryClient()
const mut = useMutation({
- mutationFn: (data) => {
- if (data && selectInsight && data.find((insight) => insight.id == selectedInsight).expand.articles.length == 1) {
+ mutationFn: (params) => {
+ if (params && selectedInsight && data.find((insight) => insight.id == selectedInsight).expand.articles.length == 1) {
throw new Error("不能删除最后一篇文章")
}
- return unlinkArticle(data)
+ return unlinkArticle(params)
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["insights", currentDate] })
diff --git a/client/web/src/lib/utils.js b/client/web/src/lib/utils.js
index d314d8c..eae5d61 100644
--- a/client/web/src/lib/utils.js
+++ b/client/web/src/lib/utils.js
@@ -1,12 +1,15 @@
import { clsx } from "clsx"
import { twMerge } from "tailwind-merge"
+export const LOCAL_TIME_OFFSITE = "+08:00"
+
export function cn(...inputs) {
return twMerge(clsx(inputs))
}
export function formatDate(date) {
- var d = new Date(isNaN(date) ? date + "T00:00:00" : date)
+ // var d = new Date(isNaN(date) ? date + "T00:00:00" + LOCAL_TIME_OFFSITE : date) // local
+ var d = new Date(isNaN(date) ? date + "T00:00:00" : date) // utc
var iso = d.toISOString()
return iso.slice(0, 10) + " " + iso.slice(11, 23) + "Z"
// return [d.getFullYear(), (d.getMonth() + 1).padLeft(), d.getDate().padLeft()].join("-") + " " + [d.getHours().padLeft(), d.getMinutes().padLeft(), d.getSeconds().padLeft()].join(":") + ".000Z"
diff --git a/client/web/src/store.js b/client/web/src/store.js
index be5fb65..e2c08cf 100644
--- a/client/web/src/store.js
+++ b/client/web/src/store.js
@@ -9,7 +9,7 @@ import { persist } from "zustand/middleware"
import axios from "axios"
import { nanoid } from "nanoid"
-import { formatDate } from "./lib/utils"
+import { formatDate, LOCAL_TIME_OFFSITE } from "./lib/utils"
const DAYS_RANGE = [1, 14]
@@ -211,7 +211,9 @@ export function getArticles(date) {
if (!date) return []
const from = formatDate(date)
- const to = formatDate(new Date(new Date(date).getTime() + 60 * 60 * 24 * 1000))
+ //const to = formatDate(new Date(new Date(date + "T00:00:00" + LOCAL_TIME_OFFSITE).getTime() + 60 * 60 * 24 * 1000))
+ const to = formatDate(new Date(new Date(date + "T00:00:00").getTime() + 60 * 60 * 24 * 1000))
+ console.log("from/to", from, to)
return pb.collection("articles").getFullList({
sort: "-created",
expand: "translation_result",
@@ -224,15 +226,15 @@ export function getInsight(id) {
}
export function getInsights(date) {
- if (!date) return null
+ if (!date) return []
const from = formatDate(date)
+ //const to = formatDate(new Date(new Date(date + "T00:00:00" + LOCAL_TIME_OFFSITE).getTime() + 60 * 60 * 24 * 1000))
const to = formatDate(new Date(new Date(date + "T00:00:00").getTime() + 60 * 60 * 24 * 1000))
// console.log("from/to", from, to)
const f = 'created >= "' + from + '" && created < "' + to + '"'
- console.log(f)
-
+ // console.log(f)
return pb.collection("insights").getFullList({
sort: "-created",
expand: "articles, articles.translation_result",
@@ -250,7 +252,7 @@ export async function getInsightDates() {
Authorization: "Bearer " + pb.authStore?.token,
},
})
- // return data.map((d) => new Date(d + "T00:00:00Z").toLocaleDateString().split("/").join("-"))
+ //return data.map((d) => new Date(d + "T00:00:00" + LOCAL_TIME_OFFSITE).toISOString().slice(0, 10))
return data
}
@@ -263,6 +265,7 @@ export async function getArticleDates() {
Authorization: "Bearer " + pb.authStore?.token,
},
})
+ //return data.map((d) => new Date(d + "T00:00:00" + LOCAL_TIME_OFFSITE).toISOString().slice(0, 10))
return data
}
From 0554e7a72f6654a8abd1893db070286ca7a888ef Mon Sep 17 00:00:00 2001
From: bigbrother666
Date: Tue, 16 Apr 2024 08:05:49 +0800
Subject: [PATCH 09/16] resolve docker yaml
---
client/backend/requirements.txt | 17 -----------------
client/compose.yaml | 1 +
2 files changed, 1 insertion(+), 17 deletions(-)
delete mode 100644 client/backend/requirements.txt
diff --git a/client/backend/requirements.txt b/client/backend/requirements.txt
deleted file mode 100644
index e2148b6..0000000
--- a/client/backend/requirements.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-fastapi
-pydantic
-uvicorn
-dashscope #optional(使用阿里灵积时安装)
-volcengine #optional(使用火山翻译时安装)
-python-docx
-BCEmbedding==0.1.3
-langchain==0.1.0
-langchain-community==0.0.9
-langchain-core==0.1.7
-langsmith==0.0.77
-# faiss-gpu for gpu environment
-faiss-cpu # for cpu-only environment
-pocketbase==0.10.0
-gne
-selenium
-chardet
\ No newline at end of file
diff --git a/client/compose.yaml b/client/compose.yaml
index 88c0a7a..35992da 100644
--- a/client/compose.yaml
+++ b/client/compose.yaml
@@ -19,3 +19,4 @@ services:
volumes:
#- ./${PROJECT_DIR}:/app/${PROJECT_DIR}
- ${EMBEDDING_MODEL_PATH}:${EMBEDDING_MODEL_PATH}
+ - ${RERANKER_MODEL_PATH}:${RERANKER_MODEL_PATH}
From 631f09252771a2957d49794f199993a0905fe595 Mon Sep 17 00:00:00 2001
From: bigbrother666
Date: Tue, 16 Apr 2024 08:08:36 +0800
Subject: [PATCH 10/16] add requirements
---
client/backend/requirements.txt | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 client/backend/requirements.txt
diff --git a/client/backend/requirements.txt b/client/backend/requirements.txt
new file mode 100644
index 0000000..573c9a9
--- /dev/null
+++ b/client/backend/requirements.txt
@@ -0,0 +1,16 @@
+fastapi
+pydantic
+uvicorn
+dashscope #optional(使用阿里灵积时安装)
+volcengine #optional(使用火山翻译时安装)
+python-docx
+BCEmbedding==0.1.3
+langchain==0.1.0
+langchain-community==0.0.9
+langchain-core==0.1.7
+langsmith==0.0.77
+# faiss-gpu for gpu environment
+faiss-cpu # for cpu-only environment
+pocketbase==0.10.0
+gne
+chardet
\ No newline at end of file
From 118e70d7b0a7da7c44aea43ea51f9671b904e122 Mon Sep 17 00:00:00 2001
From: bigbrother666
Date: Tue, 16 Apr 2024 14:33:59 +0800
Subject: [PATCH 11/16] seperate site setting
---
client/.dockerignore | 2 +-
client/.gitignore | 2 +-
client/README.md | 3 ++-
client/backend/background_task.py | 12 ++----------
client/config.ini | 9 +--------
client/sites.txt | 5 +++++
client/version | 2 +-
7 files changed, 13 insertions(+), 22 deletions(-)
create mode 100644 client/sites.txt
diff --git a/client/.dockerignore b/client/.dockerignore
index 4d15359..d420a0f 100644
--- a/client/.dockerignore
+++ b/client/.dockerignore
@@ -11,4 +11,4 @@ docker-compose.yaml
Dockerfile
README.md
backend/__pycache__
-backend/AWtest
\ No newline at end of file
+backend/WStest
\ No newline at end of file
diff --git a/client/.gitignore b/client/.gitignore
index 783ac3b..7394c6a 100644
--- a/client/.gitignore
+++ b/client/.gitignore
@@ -1,4 +1,4 @@
.env
.venv/
pb/pb_data/
-backend/AWtest/
\ No newline at end of file
+backend/WStest/
\ No newline at end of file
diff --git a/client/README.md b/client/README.md
index 19e7c26..c66dead 100644
--- a/client/README.md
+++ b/client/README.md
@@ -18,7 +18,8 @@
- character 以什么身份挖掘线索(这决定了llm的关注点和立场)
- focus 关注什么方面的线索
- focus_type 线索类型
-- good_samples 你希望llm给出的线索描述模式(给两个sample)
+- good_samples1 你希望llm给出的线索描述模式(给两个sample)
+- good_samples2 你希望llm给出的线索描述模式(给两个sample)
- bad_samples 规避的线索描述模式
- report_type 报告类型
diff --git a/client/backend/background_task.py b/client/backend/background_task.py
index 66664ca..62e104e 100644
--- a/client/backend/background_task.py
+++ b/client/backend/background_task.py
@@ -4,21 +4,13 @@
import schedule
import time
from work_process import ServiceProcesser
-import configparser
-
-config = configparser.ConfigParser()
-config.read('../config.ini')
-
-if config.has_section('sites'):
- web_pages = config['sites']
- urls = [value for key, value in web_pages.items()]
-else:
- urls = []
sp = ServiceProcesser()
def task():
+ with open('../sites.txt', 'r', encoding='utf-8') as f:
+ urls = [line.strip() for line in f.readlines() if line.strip()]
sp(sites=urls)
diff --git a/client/config.ini b/client/config.ini
index 80b5c42..f5de78f 100644
--- a/client/config.ini
+++ b/client/config.ini
@@ -6,11 +6,4 @@ focus_type = 网络安全新闻
good_sample1 = 黑客组织Rhysida声称已入侵中国国有能源公司
good_sample2 = 差不多一百万份包含未成年人数据(包括家庭地址和照片)的文件对互联网上的任何人都开放,对孩子构成威胁
bad_sample = 黑客组织活动最近频发
-report_type = 网络安全情报
-
-[sites]
-site3 = https://www.hackread.com/
-site2 = http://sh.people.com.cn/
-site1 = https://www.xuexi.cn/
-site4 = https://www.defensenews.com/
-site5 = https://www.meritalk.com
\ No newline at end of file
+report_type = 网络安全情报
\ No newline at end of file
diff --git a/client/sites.txt b/client/sites.txt
new file mode 100644
index 0000000..c4c5eba
--- /dev/null
+++ b/client/sites.txt
@@ -0,0 +1,5 @@
+https://www.hackread.com/
+http://sh.people.com.cn/
+https://www.xuexi.cn/
+https://www.defensenews.com/
+https://www.meritalk.com
\ No newline at end of file
diff --git a/client/version b/client/version
index 1474d00..22c08f7 100644
--- a/client/version
+++ b/client/version
@@ -1 +1 @@
-v0.2.0
+v0.2.1
From 1226e2d70a6bea2996d65fab5a5ae278919a7ba0 Mon Sep 17 00:00:00 2001
From: bigbrother666
Date: Tue, 16 Apr 2024 14:42:54 +0800
Subject: [PATCH 12/16] update manuel
---
client/README.md | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/client/README.md b/client/README.md
index c66dead..18e2dd2 100644
--- a/client/README.md
+++ b/client/README.md
@@ -23,12 +23,16 @@
- bad_samples 规避的线索描述模式
- report_type 报告类型
-- 【sites] 大类下面列出你的信源。一行一个网址。
+### 4、编辑 sites.txt 文件
+
+这个文件指定了需要本地执行的监控的信源,一行一个网址,支持随时更改,每次执行任务前会读取最新的。
如果你只爬取配置了专有爬虫的信源的话,可以直接编辑scrapers/__init__.py 中的scraper_map,这里都留空就好
专有爬虫的说明见 backend/scrapers/README.md
+**注:虽然wiseflow client配置了通用爬虫,对于新闻类静态网页有一定的爬取和解析效果,但我们还是强烈建议使用我们的数据订阅服务或者自写专业爬虫。**
+
## 参考:各服务注册地址
- 阿里灵积大模型接口:https://dashscope.aliyun.com/
From ac021d9ee0653a346f5c060efe1e591e2f286b3a Mon Sep 17 00:00:00 2001
From: bigbrother666
Date: Tue, 16 Apr 2024 23:07:03 +0800
Subject: [PATCH 13/16] update docker
---
client/Dockerfile.api | 8 ++++----
client/compose.yaml | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/client/Dockerfile.api b/client/Dockerfile.api
index 6e10a9b..01cf413 100644
--- a/client/Dockerfile.api
+++ b/client/Dockerfile.api
@@ -1,16 +1,16 @@
FROM python:3.10-slim
RUN apt-get update && \
- apt-get install -yq tzdata && \
- ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
- dpkg-reconfigure -f noninteractive tzdata
+ apt-get install -yq tzdata build-essential
+
+RUN ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
WORKDIR /app
COPY backend/requirements.txt requirements.txt
RUN pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
-COPY backend ./
+COPY backend .
EXPOSE 7777
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7777"]
\ No newline at end of file
diff --git a/client/compose.yaml b/client/compose.yaml
index 35992da..44f7ede 100644
--- a/client/compose.yaml
+++ b/client/compose.yaml
@@ -17,6 +17,6 @@ services:
ports:
- 7777:7777
volumes:
- #- ./${PROJECT_DIR}:/app/${PROJECT_DIR}
+ - ./${PROJECT_DIR}:/app/${PROJECT_DIR}
- ${EMBEDDING_MODEL_PATH}:${EMBEDDING_MODEL_PATH}
- ${RERANKER_MODEL_PATH}:${RERANKER_MODEL_PATH}
From 55b27c8984c02ce59fba63c74c3ca505dc933ead Mon Sep 17 00:00:00 2001
From: bigbrother666
Date: Wed, 17 Apr 2024 14:02:25 +0800
Subject: [PATCH 14/16] use pb for config
---
client/backend/__init__.py | 35 ++---
client/backend/background_task.py | 23 ++-
client/backend/get_insight.py | 50 +++++--
client/backend/get_report.py | 27 +++-
client/backend/pb_api.py | 13 +-
client/backend/scrapers/general_scraper.py | 1 +
client/backend/scrapers/simple_crawler.py | 5 +-
client/backend/work_process.py | 20 ++-
client/config.ini | 9 --
.../1713321985_created_roleplays.js | 135 ++++++++++++++++++
.../pb_migrations/1713322324_created_sites.js | 54 +++++++
.../pb_migrations/1713328405_updated_sites.js | 74 ++++++++++
.../pb_migrations/1713329959_updated_sites.js | 27 ++++
13 files changed, 404 insertions(+), 69 deletions(-)
delete mode 100644 client/config.ini
create mode 100644 client/pb/pb_migrations/1713321985_created_roleplays.js
create mode 100644 client/pb/pb_migrations/1713322324_created_sites.js
create mode 100644 client/pb/pb_migrations/1713328405_updated_sites.js
create mode 100644 client/pb/pb_migrations/1713329959_updated_sites.js
diff --git a/client/backend/__init__.py b/client/backend/__init__.py
index 0e3303c..d0fb691 100644
--- a/client/backend/__init__.py
+++ b/client/backend/__init__.py
@@ -3,7 +3,7 @@ import time
import json
import uuid
from get_logger import get_logger
-from pb_api import PbTalker
+from pb_api import pb
from get_report import get_report
from get_search import search_insight
from tranlsation_volcengine import text_translate
@@ -20,7 +20,6 @@ class BackendService:
# 2. load the llm
# self.llm = LocalLlmWrapper()
- self.pb = PbTalker(self.logger)
self.memory = {}
# self.scholar = Scholar(initial_file_dir=os.path.join(self.project_dir, "files"), use_gpu=use_gpu)
self.logger.info(f'{self.name} init success.')
@@ -33,7 +32,7 @@ class BackendService:
:return: 成功的话返回更新后的insight_id(其实跟原id一样), 不成功返回空字符
"""
self.logger.debug(f'got new report request insight_id {insight_id}')
- insight = self.pb.read('insights', filter=f'id="{insight_id}"')
+ insight = pb.read('insights', filter=f'id="{insight_id}"')
if not insight:
self.logger.error(f'insight {insight_id} not found')
return self.build_out(-2, 'insight not found')
@@ -43,8 +42,7 @@ class BackendService:
self.logger.error(f'insight {insight_id} has no articles')
return self.build_out(-2, 'can not find articles for insight')
- article_list = [self.pb.read('articles',
- fields=['title', 'abstract', 'content', 'url', 'publish_time'], filter=f'id="{_id}"')
+ article_list = [pb.read('articles', fields=['title', 'abstract', 'content', 'url', 'publish_time'], filter=f'id="{_id}"')
for _id in article_ids]
article_list = [_article[0] for _article in article_list if _article]
@@ -66,7 +64,7 @@ class BackendService:
if flag:
file = open(docx_file, 'rb')
- message = self.pb.upload('insights', insight_id, 'docx', f'{insight_id}.docx', file)
+ message = pb.upload('insights', insight_id, 'docx', f'{insight_id}.docx', file)
file.close()
if message:
self.logger.debug(f'report success finish and update to pb-{message}')
@@ -96,8 +94,7 @@ class BackendService:
en_texts = []
k = 1
for article_id in article_ids:
- raw_article = self.pb.read(collection_name='articles', fields=['abstract', 'title', 'translation_result'],
- filter=f'id="{article_id}"')
+ raw_article = pb.read(collection_name='articles', fields=['abstract', 'title', 'translation_result'], filter=f'id="{article_id}"')
if not raw_article or not raw_article[0]:
self.logger.warning(f'get article {article_id} failed, skipping')
flag = -2
@@ -118,14 +115,11 @@ class BackendService:
translate_result = text_translate(en_texts, logger=self.logger)
if translate_result and len(translate_result) == 2*len(key_cache):
for i in range(0, len(translate_result), 2):
- related_id = self.pb.add(collection_name='article_translation',
- body={'title': translate_result[i], 'abstract': translate_result[i+1],
- 'raw': key_cache[int(i/2)]})
+ related_id = pb.add(collection_name='article_translation', body={'title': translate_result[i], 'abstract': translate_result[i+1], 'raw': key_cache[int(i/2)]})
if not related_id:
self.logger.warning(f'write article_translation {key_cache[int(i/2)]} failed')
else:
- _ = self.pb.update(collection_name='articles', id=key_cache[int(i/2)],
- body={'translation_result': related_id})
+ _ = pb.update(collection_name='articles', id=key_cache[int(i/2)], body={'translation_result': related_id})
if not _:
self.logger.warning(f'update article {key_cache[int(i/2)]} failed')
self.logger.debug('done')
@@ -148,14 +142,11 @@ class BackendService:
translate_result = text_translate(en_texts, logger=self.logger)
if translate_result and len(translate_result) == 2*len(key_cache):
for i in range(0, len(translate_result), 2):
- related_id = self.pb.add(collection_name='article_translation',
- body={'title': translate_result[i], 'abstract': translate_result[i+1],
- 'raw': key_cache[int(i/2)]})
+ related_id = pb.add(collection_name='article_translation', body={'title': translate_result[i], 'abstract': translate_result[i+1], 'raw': key_cache[int(i/2)]})
if not related_id:
self.logger.warning(f'write article_translation {key_cache[int(i/2)]} failed')
else:
- _ = self.pb.update(collection_name='articles', id=key_cache[int(i/2)],
- body={'translation_result': related_id})
+ _ = pb.update(collection_name='articles', id=key_cache[int(i/2)], body={'translation_result': related_id})
if not _:
self.logger.warning(f'update article {key_cache[int(i/2)]} failed')
self.logger.debug('done')
@@ -172,14 +163,14 @@ class BackendService:
:return: 成功的话返回更新后的insight_id(其实跟原id一样), 不成功返回空字符
"""
self.logger.debug(f'got search request for insight: {insight_id}')
- insight = self.pb.read('insights', filter=f'id="{insight_id}"')
+ insight = pb.read('insights', filter=f'id="{insight_id}"')
if not insight:
self.logger.error(f'insight {insight_id} not found')
return self.build_out(-2, 'insight not found')
article_ids = insight[0]['articles']
if article_ids:
- article_list = [self.pb.read('articles', fields=['url'], filter=f'id="{_id}"') for _id in article_ids]
+ article_list = [pb.read('articles', fields=['url'], filter=f'id="{_id}"') for _id in article_ids]
url_list = [_article[0]['url'] for _article in article_list if _article]
else:
url_list = []
@@ -190,7 +181,7 @@ class BackendService:
return self.build_out(flag, 'search engine error or no result')
for item in search_result:
- new_article_id = self.pb.add(collection_name='articles', body=item)
+ new_article_id = pb.add(collection_name='articles', body=item)
if new_article_id:
article_ids.append(new_article_id)
else:
@@ -198,7 +189,7 @@ class BackendService:
with open(os.path.join(self.cache_url, 'cache_articles.json'), 'a', encoding='utf-8') as f:
json.dump(item, f, ensure_ascii=False, indent=4)
- message = self.pb.update(collection_name='insights', id=insight_id, body={'articles': article_ids})
+ message = pb.update(collection_name='insights', id=insight_id, body={'articles': article_ids})
if message:
self.logger.debug(f'insight search success finish and update to pb-{message}')
return self.build_out(11, insight_id)
diff --git a/client/backend/background_task.py b/client/backend/background_task.py
index 62e104e..26281c1 100644
--- a/client/backend/background_task.py
+++ b/client/backend/background_task.py
@@ -4,18 +4,31 @@
import schedule
import time
from work_process import ServiceProcesser
+from pb_api import pb
sp = ServiceProcesser()
+counter = 0
+# 每小时唤醒一次,如果pb的sites表中有信源,会挑取符合周期的信源执行,没有没有的话,则每24小时执行专有爬虫一次
def task():
- with open('../sites.txt', 'r', encoding='utf-8') as f:
- urls = [line.strip() for line in f.readlines() if line.strip()]
- sp(sites=urls)
+ global counter
+ sites = pb.read('sites', filter='activated=True')
+ urls = []
+ for site in sites:
+ if not site['per_hours'] or not site['url']:
+ continue
+ if counter % site['per_hours'] == 0:
+ urls.append(site['url'])
+ counter += 1
+ if urls:
+ sp(sites=urls)
+ else:
+ if counter % 24 == 0:
+ sp()
-# 每天凌晨1点运行任务
-schedule.every().day.at("01:17").do(task)
+schedule.every().hour.do(task)
while True:
schedule.run_pending()
diff --git a/client/backend/get_insight.py b/client/backend/get_insight.py
index df2aefc..fa5e667 100644
--- a/client/backend/get_insight.py
+++ b/client/backend/get_insight.py
@@ -8,37 +8,63 @@ from general_utils import isChinesePunctuation, is_chinese
from tranlsation_volcengine import text_translate
import time
import re
-import configparser
+from pb_api import pb
+
max_tokens = 4000
relation_theshold = 0.525
-config = configparser.ConfigParser()
-config.read('../config.ini')
+role_config = pb.read(collection_name='roleplays', filter=f'activated=True')
+_role_config_id = ''
+if role_config:
+ character = role_config[0]['character']
+ focus = role_config[0]['focus']
+ focus_type = role_config[0]['focus_type']
+ good_sample1 = role_config[0]['good_sample1']
+ good_sample2 = role_config[0]['good_sample2']
+ bad_sample = role_config[0]['bad_sample']
+ _role_config_id = role_config[0]['id']
+else:
+ character, good_sample1, focus, focus_type, good_sample2, bad_sample = '', '', '', '', '', ''
+
+if not character:
+ character = input('请为首席情报官指定角色设定(eg. 来自中国的网络安全情报专家):\n')
+ _role_config_id = pb.add(collection_name='roleplays', body={'character': character, 'activated': True})
+
+if not _role_config_id:
+ raise Exception('pls check pb data, 无法获取角色设定')
+
+if not (focus and focus_type and good_sample1 and good_sample2 and bad_sample):
+ focus = input('请为首席情报官指定关注点(eg. 中国关注的网络安全新闻):\n')
+ focus_type = input('请为首席情报官指定关注点类型(eg. 网络安全新闻):\n')
+ good_sample1 = input('请给出一个你期望的情报描述示例(eg. 黑客组织Rhysida声称已入侵中国国有能源公司): \n')
+ good_sample2 = input('请再给出一个理想示例(eg. 差不多一百万份包含未成年人数据(包括家庭地址和照片)的文件对互联网上的任何人都开放,对孩子构成威胁): \n')
+ bad_sample = input('请给出一个你不期望的情报描述示例(eg. 黑客组织活动最近频发): \n')
+ _ = pb.update(collection_name='roleplays', id=_role_config_id, body={'focus': focus, 'focus_type': focus_type, 'good_sample1': good_sample1, 'good_sample2': good_sample2, 'bad_sample': bad_sample})
# 实践证明,如果强调让llm挖掘我国值得关注的线索,则挖掘效果不好(容易被新闻内容误导,错把别的国家当成我国,可能这时新闻内有我国这样的表述)
# step by step 如果是内心独白方式,输出格式包含两种,难度增加了,qwen-max不能很好的适应,也许可以改成两步,第一步先输出线索列表,第二步再会去找对应的新闻编号
# 但从实践来看,这样做的性价比并不高,且会引入新的不确定性。
-_first_stage_prompt = f'''你是一名{config['prompts']['character']},你将被给到一个新闻列表,新闻文章用XML标签分隔。请对此进行分析,挖掘出特别值得{config['prompts']['focus']}线索。你给出的线索应该足够具体,而不是同类型新闻的归类描述,好的例子如:
-"""{config['prompts']['good_sample1']}"""
+_first_stage_prompt = f'''你是一名{character},你将被给到一个新闻列表,新闻文章用XML标签分隔。请对此进行分析,挖掘出特别值得{focus}线索。你给出的线索应该足够具体,而不是同类型新闻的归类描述,好的例子如:
+"""{good_sample1}"""
不好的例子如:
-"""{config['prompts']['bad_sample']}"""
+"""{bad_sample}"""
请从头到尾仔细阅读每一条新闻的内容,不要遗漏,然后列出值得关注的线索,每条线索都用一句话进行描述,最终按一条一行的格式输出,并整体用三引号包裹,如下所示:
"""
-{config['prompts']['good_sample1']}
-{config['prompts']['good_sample2']}
+{good_sample1}
+{good_sample2}
"""
不管新闻列表是何种语言,请仅用中文输出分析结果。'''
-_rewrite_insight_prompt = f'''你是一名{config['prompts']['character']},你将被给到一个新闻列表,新闻文章用 XML 标签分隔。请对此进行分析,从中挖掘出一条最值得关注的{config['prompts']['focus_type']}线索。你给出的线索应该足够具体,而不是同类型新闻的归类描述,好的例子如:
-"""{config['prompts']['good_sample1']}"""
+_rewrite_insight_prompt = f'''你是一名{character},你将被给到一个新闻列表,新闻文章用XML标签分隔。请对此进行分析,从中挖掘出一条最值得关注的{focus_type}线索。你给出的线索应该足够具体,而不是同类型新闻的归类描述,好的例子如:
+"""{good_sample1}"""
不好的例子如:
-"""{config['prompts']['bad_sample']}"""
+"""{bad_sample}"""
请保证只输出一条最值得关注的线索,线索请用一句话描述,并用三引号包裹输出,如下所示:
-"""{config['prompts']['good_sample1']}"""
+"""{good_sample1}"""
不管新闻列表是何种语言,请仅用中文输出分析结果。'''
diff --git a/client/backend/get_report.py b/client/backend/get_report.py
index 334ba20..90242cd 100644
--- a/client/backend/get_report.py
+++ b/client/backend/get_report.py
@@ -7,14 +7,31 @@ from docx.shared import Pt, RGBColor
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from datetime import datetime
from general_utils import isChinesePunctuation
-import configparser
+from pb_api import pb
# qwen-72b-chat支持最大30k输入,考虑prompt其他部分,content不应超过30000字符长度
# 如果换qwen-max(最大输入6k),这里就要换成6000,但这样很多文章不能分析了
# 本地部署模型(qwen-14b这里可能仅支持4k输入,可能根本这套模式就行不通)
max_input_tokens = 30000
-config = configparser.ConfigParser()
-config.read('../config.ini')
+role_config = pb.read(collection_name='roleplays', filter=f'activated=True')
+_role_config_id = ''
+if role_config:
+ character = role_config[0]['character']
+ report_type = role_config[0]['report_type']
+ _role_config_id = role_config[0]['id']
+else:
+ character, report_type = '', ''
+
+if not character:
+ character = input('请为首席情报官指定角色设定(eg. 来自中国的网络安全情报专家):\n')
+ _role_config_id = pb.add(collection_name='roleplays', body={'character': character, 'activated': True})
+
+if not _role_config_id:
+ raise Exception('pls check pb data无法获取角色设定')
+
+if not report_type:
+ report_type = input('请为首席情报官指定报告类型(eg. 网络安全情报):\n')
+ _ = pb.update(collection_name='roleplays', id=_role_config_id, body={'report_type': report_type})
def get_report(insigt: str, articles: list[dict], memory: str, topics: list[str], comment: str, docx_file: str, logger=None) -> (bool, str):
@@ -44,7 +61,7 @@ def get_report(insigt: str, articles: list[dict], memory: str, topics: list[str]
paragraphs = re.findall("、(.*?)】", memory)
if set(topics) <= set(paragraphs):
logger.debug("no change in Topics, need modified the report")
- system_prompt = f'''你是一名{config['prompts']['character']},你近日向上级提交了一份{config['prompts']['report_type']}报告,如下是报告原文。接下来你将收到来自上级部门的修改意见,请据此修改你的报告:
+ system_prompt = f'''你是一名{character},你近日向上级提交了一份{report_type}报告,如下是报告原文。接下来你将收到来自上级部门的修改意见,请据此修改你的报告:
报告原文:
"""{memory}"""
'''
@@ -66,7 +83,7 @@ def get_report(insigt: str, articles: list[dict], memory: str, topics: list[str]
break
logger.debug(f"articles context length: {len(texts)}")
- system_prompt = f'''你是一名{config['prompts']['character']},在近期的工作中我们从所关注的网站中发现了一条重要的{config['prompts']['report_type']}线索,线索和相关文章(用XML标签分隔)如下:
+ system_prompt = f'''你是一名{character},在近期的工作中我们从所关注的网站中发现了一条重要的{report_type}线索,线索和相关文章(用XML标签分隔)如下:
情报线索: """{insigt} """
相关文章:
{texts}
diff --git a/client/backend/pb_api.py b/client/backend/pb_api.py
index bd5d818..981ddc3 100644
--- a/client/backend/pb_api.py
+++ b/client/backend/pb_api.py
@@ -2,11 +2,15 @@ import os
from pocketbase import PocketBase # Client also works the same
from pocketbase.client import FileUpload
from typing import BinaryIO
+from get_logger import get_logger
class PbTalker:
- def __init__(self, logger=None) -> None:
- self.logger = logger
+ def __init__(self) -> None:
+ self.project_dir = os.environ.get("PROJECT_DIR", "")
+ # 1. base initialization
+ os.makedirs(self.project_dir, exist_ok=True)
+ self.logger = get_logger(name='pb_talker', file=os.path.join(self.project_dir, 'pb_talker.log'))
url = f"http://{os.environ.get('PB_API_BASE', '127.0.0.1:8090')}"
self.logger.debug(f"initializing pocketbase client: {url}")
self.client = PocketBase(url)
@@ -17,7 +21,7 @@ class PbTalker:
email, password = auth.split('|')
_ = self.client.admins.auth_with_password(email, password)
if _:
- self.logger.info(f"pocketbase ready authenticated as admin - {url}")
+ self.logger.info(f"pocketbase ready authenticated as admin - {email}")
else:
raise Exception(f"pocketbase auth failed")
@@ -78,3 +82,6 @@ class PbTalker:
self.logger.error(f"pocketbase update failed: {e}")
return ''
return res.id
+
+
+pb = PbTalker()
diff --git a/client/backend/scrapers/general_scraper.py b/client/backend/scrapers/general_scraper.py
index e693ec7..9fc226d 100644
--- a/client/backend/scrapers/general_scraper.py
+++ b/client/backend/scrapers/general_scraper.py
@@ -17,6 +17,7 @@ import os
header = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/604.1 Edg/112.0.100.0'}
project_dir = os.environ.get("PROJECT_DIR", "")
+os.makedirs(project_dir, exist_ok=True)
logger = get_logger(name='general_scraper', file=os.path.join(project_dir, f'general_scraper.log'))
diff --git a/client/backend/scrapers/simple_crawler.py b/client/backend/scrapers/simple_crawler.py
index 94f3785..60891bf 100644
--- a/client/backend/scrapers/simple_crawler.py
+++ b/client/backend/scrapers/simple_crawler.py
@@ -13,6 +13,7 @@ header = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/604.1 Edg/112.0.100.0'}
project_dir = os.environ.get("PROJECT_DIR", "")
+os.makedirs(project_dir, exist_ok=True)
logger = get_logger(name='simple_crawler', file=os.path.join(project_dir, f'simple_crawler.log'))
@@ -26,11 +27,11 @@ def simple_crawler(url: str | Path) -> (int, dict):
rawdata = response.content
encoding = chardet.detect(rawdata)['encoding']
text = rawdata.decode(encoding)
+ result = extractor.extract(text)
except Exception as e:
- logger.error(e)
+ logger.warning(f"cannot get content from {url}\n{e}")
return -7, {}
- result = extractor.extract(text)
if not result:
logger.error(f"gne cannot extract {url}")
return 0, {}
diff --git a/client/backend/work_process.py b/client/backend/work_process.py
index 05ccae1..f51dbc1 100644
--- a/client/backend/work_process.py
+++ b/client/backend/work_process.py
@@ -5,7 +5,7 @@ from get_logger import get_logger
from datetime import datetime, timedelta, date
from scrapers import scraper_map
from scrapers.general_scraper import general_scraper
-from pb_api import PbTalker
+from pb_api import pb
from urllib.parse import urlparse
from get_insight import get_insight
from general_utils import is_chinese
@@ -27,7 +27,6 @@ class ServiceProcesser:
self.cache_url = os.path.join(self.project_dir, name)
os.makedirs(self.cache_url, exist_ok=True)
self.logger = get_logger(name=self.name, file=os.path.join(self.project_dir, f'{self.name}.log'))
- self.pb = PbTalker(self.logger)
# 2. load the llm
# self.llm = LocalLlmWrapper() # if you use the local-llm
@@ -49,7 +48,7 @@ class ServiceProcesser:
self.logger.debug(f'clear cache -- {cache}')
# 从pb数据库中读取所有文章url
# 这里publish_time用int格式,综合考虑下这个是最容易操作的模式,虽然糙了点
- existing_articles = self.pb.read(collection_name='articles', fields=['id', 'title', 'url'], filter=f'publish_time>{expiration_str}')
+ existing_articles = pb.read(collection_name='articles', fields=['id', 'title', 'url'], filter=f'publish_time>{expiration_str}')
all_title = {}
existings = []
for article in existing_articles:
@@ -84,7 +83,7 @@ class ServiceProcesser:
value['content'] = f"({from_site} 报道){value['content']}"
value['images'] = json.dumps(value['images'])
- article_id = self.pb.add(collection_name='articles', body=value)
+ article_id = pb.add(collection_name='articles', body=value)
if article_id:
cache[article_id] = value
@@ -104,13 +103,13 @@ class ServiceProcesser:
for insight in new_insights:
if not insight['content']:
continue
- insight_id = self.pb.add(collection_name='insights', body=insight)
+ insight_id = pb.add(collection_name='insights', body=insight)
if not insight_id:
self.logger.warning(f'write insight {insight} to pb failed, writing to cache_file')
with open(os.path.join(self.cache_url, 'cache_insights.json'), 'a', encoding='utf-8') as f:
json.dump(insight, f, ensure_ascii=False, indent=4)
for article_id in insight['articles']:
- raw_article = self.pb.read(collection_name='articles', fields=['abstract', 'title', 'translation_result'], filter=f'id="{article_id}"')
+ raw_article = pb.read(collection_name='articles', fields=['abstract', 'title', 'translation_result'], filter=f'id="{article_id}"')
if not raw_article or not raw_article[0]:
self.logger.warning(f'get article {article_id} failed, skipping')
continue
@@ -120,11 +119,11 @@ class ServiceProcesser:
continue
translate_text = text_translate([raw_article[0]['title'], raw_article[0]['abstract']], target_language='zh', logger=self.logger)
if translate_text:
- related_id = self.pb.add(collection_name='article_translation', body={'title': translate_text[0], 'abstract': translate_text[1], 'raw': article_id})
+ related_id = pb.add(collection_name='article_translation', body={'title': translate_text[0], 'abstract': translate_text[1], 'raw': article_id})
if not related_id:
self.logger.warning(f'write article_translation {article_id} failed')
else:
- _ = self.pb.update(collection_name='articles', id=article_id, body={'translation_result': related_id})
+ _ = pb.update(collection_name='articles', id=article_id, body={'translation_result': related_id})
if not _:
self.logger.warning(f'update article {article_id} failed')
else:
@@ -140,8 +139,7 @@ class ServiceProcesser:
else:
text_for_insight = text_translate([value['title']], logger=self.logger)
if text_for_insight:
- insight_id = self.pb.add(collection_name='insights',
- body={'content': text_for_insight[0], 'articles': [key]})
+ insight_id = pb.add(collection_name='insights', body={'content': text_for_insight[0], 'articles': [key]})
if not insight_id:
self.logger.warning(f'write insight {text_for_insight[0]} to pb failed, writing to cache_file')
with open(os.path.join(self.cache_url, 'cache_insights.json'), 'a',
@@ -158,7 +156,7 @@ class ServiceProcesser:
try:
snapshot = requests.get(f"{self.snap_short_server}/zip", {'url': value['url']}, timeout=60)
file = open(snapshot.text, 'rb')
- _ = self.pb.upload('articles', key, 'snapshot', key, file)
+ _ = pb.upload('articles', key, 'snapshot', key, file)
file.close()
except Exception as e:
self.logger.warning(f'error when snapshot {value["url"]}, {e}')
diff --git a/client/config.ini b/client/config.ini
deleted file mode 100644
index f5de78f..0000000
--- a/client/config.ini
+++ /dev/null
@@ -1,9 +0,0 @@
-; config.ini
-[prompts]
-character = 来自中国的网络安全情报专家
-focus = 中国关注的网络安全新闻
-focus_type = 网络安全新闻
-good_sample1 = 黑客组织Rhysida声称已入侵中国国有能源公司
-good_sample2 = 差不多一百万份包含未成年人数据(包括家庭地址和照片)的文件对互联网上的任何人都开放,对孩子构成威胁
-bad_sample = 黑客组织活动最近频发
-report_type = 网络安全情报
\ No newline at end of file
diff --git a/client/pb/pb_migrations/1713321985_created_roleplays.js b/client/pb/pb_migrations/1713321985_created_roleplays.js
new file mode 100644
index 0000000..629a740
--- /dev/null
+++ b/client/pb/pb_migrations/1713321985_created_roleplays.js
@@ -0,0 +1,135 @@
+///
+migrate((db) => {
+ const collection = new Collection({
+ "id": "4rpge043645sp4j",
+ "created": "2024-04-17 02:46:25.373Z",
+ "updated": "2024-04-17 02:46:25.373Z",
+ "name": "roleplays",
+ "type": "base",
+ "system": false,
+ "schema": [
+ {
+ "system": false,
+ "id": "ixk4pwsb",
+ "name": "activated",
+ "type": "bool",
+ "required": false,
+ "presentable": false,
+ "unique": false,
+ "options": {}
+ },
+ {
+ "system": false,
+ "id": "tmak73c7",
+ "name": "character",
+ "type": "text",
+ "required": false,
+ "presentable": false,
+ "unique": false,
+ "options": {
+ "min": null,
+ "max": null,
+ "pattern": ""
+ }
+ },
+ {
+ "system": false,
+ "id": "6iuxuwhb",
+ "name": "focus",
+ "type": "text",
+ "required": false,
+ "presentable": false,
+ "unique": false,
+ "options": {
+ "min": null,
+ "max": null,
+ "pattern": ""
+ }
+ },
+ {
+ "system": false,
+ "id": "axmc2huy",
+ "name": "focus_type",
+ "type": "text",
+ "required": false,
+ "presentable": false,
+ "unique": false,
+ "options": {
+ "min": null,
+ "max": null,
+ "pattern": ""
+ }
+ },
+ {
+ "system": false,
+ "id": "gop61pjt",
+ "name": "good_sample1",
+ "type": "text",
+ "required": false,
+ "presentable": false,
+ "unique": false,
+ "options": {
+ "min": null,
+ "max": null,
+ "pattern": ""
+ }
+ },
+ {
+ "system": false,
+ "id": "qmy5cofa",
+ "name": "good_sample2",
+ "type": "text",
+ "required": false,
+ "presentable": false,
+ "unique": false,
+ "options": {
+ "min": null,
+ "max": null,
+ "pattern": ""
+ }
+ },
+ {
+ "system": false,
+ "id": "h8gafaci",
+ "name": "bad_sample",
+ "type": "text",
+ "required": false,
+ "presentable": false,
+ "unique": false,
+ "options": {
+ "min": null,
+ "max": null,
+ "pattern": ""
+ }
+ },
+ {
+ "system": false,
+ "id": "m2ug5sfd",
+ "name": "report_type",
+ "type": "text",
+ "required": false,
+ "presentable": false,
+ "unique": false,
+ "options": {
+ "min": null,
+ "max": null,
+ "pattern": ""
+ }
+ }
+ ],
+ "indexes": [],
+ "listRule": null,
+ "viewRule": null,
+ "createRule": null,
+ "updateRule": null,
+ "deleteRule": null,
+ "options": {}
+ });
+
+ return Dao(db).saveCollection(collection);
+}, (db) => {
+ const dao = new Dao(db);
+ const collection = dao.findCollectionByNameOrId("4rpge043645sp4j");
+
+ return dao.deleteCollection(collection);
+})
diff --git a/client/pb/pb_migrations/1713322324_created_sites.js b/client/pb/pb_migrations/1713322324_created_sites.js
new file mode 100644
index 0000000..2672a1b
--- /dev/null
+++ b/client/pb/pb_migrations/1713322324_created_sites.js
@@ -0,0 +1,54 @@
+///
+migrate((db) => {
+ const collection = new Collection({
+ "id": "sma08jpi5rkoxnh",
+ "created": "2024-04-17 02:52:04.291Z",
+ "updated": "2024-04-17 02:52:04.291Z",
+ "name": "sites",
+ "type": "base",
+ "system": false,
+ "schema": [
+ {
+ "system": false,
+ "id": "6qo4l7og",
+ "name": "url",
+ "type": "url",
+ "required": false,
+ "presentable": false,
+ "unique": false,
+ "options": {
+ "exceptDomains": null,
+ "onlyDomains": null
+ }
+ },
+ {
+ "system": false,
+ "id": "lgr1quwi",
+ "name": "per_hours",
+ "type": "number",
+ "required": false,
+ "presentable": false,
+ "unique": false,
+ "options": {
+ "min": 1,
+ "max": 24,
+ "noDecimal": false
+ }
+ }
+ ],
+ "indexes": [],
+ "listRule": null,
+ "viewRule": null,
+ "createRule": null,
+ "updateRule": null,
+ "deleteRule": null,
+ "options": {}
+ });
+
+ return Dao(db).saveCollection(collection);
+}, (db) => {
+ const dao = new Dao(db);
+ const collection = dao.findCollectionByNameOrId("sma08jpi5rkoxnh");
+
+ return dao.deleteCollection(collection);
+})
diff --git a/client/pb/pb_migrations/1713328405_updated_sites.js b/client/pb/pb_migrations/1713328405_updated_sites.js
new file mode 100644
index 0000000..f1f8417
--- /dev/null
+++ b/client/pb/pb_migrations/1713328405_updated_sites.js
@@ -0,0 +1,74 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("sma08jpi5rkoxnh")
+
+ // update
+ collection.schema.addField(new SchemaField({
+ "system": false,
+ "id": "6qo4l7og",
+ "name": "url",
+ "type": "url",
+ "required": true,
+ "presentable": false,
+ "unique": false,
+ "options": {
+ "exceptDomains": null,
+ "onlyDomains": null
+ }
+ }))
+
+ // update
+ collection.schema.addField(new SchemaField({
+ "system": false,
+ "id": "lgr1quwi",
+ "name": "per_hours",
+ "type": "number",
+ "required": true,
+ "presentable": false,
+ "unique": false,
+ "options": {
+ "min": 1,
+ "max": 24,
+ "noDecimal": false
+ }
+ }))
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("sma08jpi5rkoxnh")
+
+ // update
+ collection.schema.addField(new SchemaField({
+ "system": false,
+ "id": "6qo4l7og",
+ "name": "url",
+ "type": "url",
+ "required": false,
+ "presentable": false,
+ "unique": false,
+ "options": {
+ "exceptDomains": null,
+ "onlyDomains": null
+ }
+ }))
+
+ // update
+ collection.schema.addField(new SchemaField({
+ "system": false,
+ "id": "lgr1quwi",
+ "name": "per_hours",
+ "type": "number",
+ "required": false,
+ "presentable": false,
+ "unique": false,
+ "options": {
+ "min": 1,
+ "max": 24,
+ "noDecimal": false
+ }
+ }))
+
+ return dao.saveCollection(collection)
+})
diff --git a/client/pb/pb_migrations/1713329959_updated_sites.js b/client/pb/pb_migrations/1713329959_updated_sites.js
new file mode 100644
index 0000000..a49e806
--- /dev/null
+++ b/client/pb/pb_migrations/1713329959_updated_sites.js
@@ -0,0 +1,27 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("sma08jpi5rkoxnh")
+
+ // add
+ collection.schema.addField(new SchemaField({
+ "system": false,
+ "id": "8x8n2a47",
+ "name": "activated",
+ "type": "bool",
+ "required": false,
+ "presentable": false,
+ "unique": false,
+ "options": {}
+ }))
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("sma08jpi5rkoxnh")
+
+ // remove
+ collection.schema.removeField("8x8n2a47")
+
+ return dao.saveCollection(collection)
+})
From 7349d6fa3aeea985c94de41111c1b4344881d210 Mon Sep 17 00:00:00 2001
From: bigbrother666
Date: Wed, 17 Apr 2024 18:28:10 +0800
Subject: [PATCH 15/16] improve sth
---
asset/371709012494.jpg | Bin 91693 -> 0 bytes
client/backend/background_task.py | 4 +++-
client/backend/get_insight.py | 12 ++++++------
client/backend/get_report.py | 4 ++--
client/backend/scrapers/simple_crawler.py | 2 +-
client/sites.txt | 5 -----
6 files changed, 12 insertions(+), 15 deletions(-)
delete mode 100644 asset/371709012494.jpg
delete mode 100644 client/sites.txt
diff --git a/asset/371709012494.jpg b/asset/371709012494.jpg
deleted file mode 100644
index b4d58f50f7d9460b8cd565ccb4e11f450f5e1572..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 91693
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