diff --git a/.config/ci.yml b/.config/ci.yml index 5534e26590..b3578fb66b 100644 --- a/.config/ci.yml +++ b/.config/ci.yml @@ -1,195 +1,11 @@ -#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -# Firefish configuration -#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -# ┌─────┐ -#───┘ URL └───────────────────────────────────────────────────── - -# Final accessible URL seen by a user. -url: https://example.tld/ - -# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE -# URL SETTINGS AFTER THAT! - -# ┌───────────────────────┐ -#───┘ Port and TLS settings └─────────────────────────────────── - -# -# Misskey requires a reverse proxy to support HTTPS connections. -# -# +----- https://example.tld/ ------------+ -# +------+ |+-------------+ +----------------+| -# | User | ---> || Proxy (443) | ---> | Misskey (3000) || -# +------+ |+-------------+ +----------------+| -# +---------------------------------------+ -# -# You need to set up a reverse proxy. (e.g. nginx) -# An encrypted connection with HTTPS is highly recommended -# because tokens may be transferred in GET requests. - -# The port that your Misskey server should listen on. +url: http://localhost:3000 port: 3000 - -# ┌──────────────────────────┐ -#───┘ PostgreSQL configuration └──────────────────────────────── - db: host: postgres port: 5432 - - # Database name - db: postgres - - # Auth - user: postgres - pass: test - - # Whether disable Caching queries - #disableCache: true - - # Extra Connection options - #extra: - # ssl: true - -# ┌─────────────────────┐ -#───┘ Redis configuration └───────────────────────────────────── - + db: firefish_db + user: firefish + pass: password redis: host: redis port: 6379 - #family: 0 # 0=Both, 4=IPv4, 6=IPv6 - #pass: example-pass - #prefix: example-prefix - #db: 1 - -# ┌─────────────────────────────┐ -#───┘ Elasticsearch configuration └───────────────────────────── - -#elasticsearch: -# host: localhost -# port: 9200 -# ssl: false -# user: -# pass: - -# ┌───────────────┐ -#───┘ ID generation └─────────────────────────────────────────── - -# You can select the ID generation method. -# You don't usually need to change this setting, but you can -# change it according to your preferences. - -# Available methods: -# aid ... Short, Millisecond accuracy -# meid ... Similar to ObjectID, Millisecond accuracy -# ulid ... Millisecond accuracy -# objectid ... This is left for backward compatibility - -# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE -# ID SETTINGS AFTER THAT! - -id: 'aid' - -# ┌─────────────────────┐ -#───┘ Other configuration └───────────────────────────────────── - -# Max note length, should be < 8000. -#maxNoteLength: 3000 - -# Whether disable HSTS -#disableHsts: true - -# Number of worker processes -#clusterLimit: 1 - -# Job concurrency per worker -# deliverJobConcurrency: 128 -# inboxJobConcurrency: 16 - -# Job rate limiter -# deliverJobPerSec: 128 -# inboxJobPerSec: 16 - -# Job attempts -# deliverJobMaxAttempts: 12 -# inboxJobMaxAttempts: 8 - -# IP address family used for outgoing request (ipv4, ipv6 or dual) -#outgoingAddressFamily: ipv4 - -# Syslog option -#syslog: -# host: localhost -# port: 514 - -# Proxy for HTTP/HTTPS -#proxy: http://127.0.0.1:3128 - -#proxyBypassHosts: [ -# 'example.com', -# '192.0.2.8' -#] - -# Proxy for SMTP/SMTPS -#proxySmtp: http://127.0.0.1:3128 # use HTTP/1.1 CONNECT -#proxySmtp: socks4://127.0.0.1:1080 # use SOCKS4 -#proxySmtp: socks5://127.0.0.1:1080 # use SOCKS5 - -# Media Proxy -#mediaProxy: https://example.com/proxy - -# Proxy remote files (default: false) -#proxyRemoteFiles: true - -#allowedPrivateNetworks: [ -# '127.0.0.1/32' -#] - -# Upload or download file size limits (bytes) -#maxFileSize: 262144000 - -# Managed hosting settings -# !!!!!!!!!! -# >>>>>> NORMAL SELF-HOSTERS, STAY AWAY! <<<<<< -# >>>>>> YOU DON'T NEED THIS! <<<<<< -# !!!!!!!!!! -# Each category is optional, but if each item in each category is mandatory! -# If you mess this up, that's on you, you've been warned... - -#maxUserSignups: 100 -#isManagedHosting: true -#deepl: -# managed: true -# authKey: '' -# isPro: false -# -#email: -# managed: true -# address: 'example@email.com' -# host: 'email.com' -# port: 587 -# user: 'example@email.com' -# pass: '' -# useImplicitSslTls: false -# -#objectStorage: -# managed: true -# baseUrl: '' -# bucket: '' -# prefix: '' -# endpoint: '' -# region: '' -# accessKey: '' -# secretKey: '' -# useSsl: true -# connnectOverProxy: false -# setPublicReadOnUpload: true -# s3ForcePathStyle: true - -# !!!!!!!!!! -# >>>>>> AGAIN, NORMAL SELF-HOSTERS, STAY AWAY! <<<<<< -# >>>>>> YOU DON'T NEED THIS, ABOVE SETTINGS ARE FOR MANAGED HOSTING ONLY! <<<<<< -# !!!!!!!!!! - -# Seriously. Do NOT fill out the above settings if you're self-hosting. -# They're much better off being set from the control panel. diff --git a/.dockerignore b/.dockerignore index 3819d675c8..30e75f6237 100644 --- a/.dockerignore +++ b/.dockerignore @@ -51,12 +51,11 @@ title.svg /dev /docs /scripts +!/scripts/copy-assets.mjs biome.json -COPYING CODE_OF_CONDUCT.md CONTRIBUTING.md Dockerfile -LICENSE Procfile README.md SECURITY.md diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000..8f4f4d54c7 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,144 @@ +image: docker.io/rust:slim-bookworm + +services: + - name: docker.io/groonga/pgroonga:latest-alpine-12-slim + alias: postgres + - name: docker.io/redis:7-alpine + alias: redis + +workflow: + rules: + - if: $CI_PROJECT_PATH == 'firefish/firefish' + when: always + - if: $CI_MERGE_REQUEST_PROJECT_PATH == 'firefish/firefish' + when: always + - when: never + +cache: + paths: + - node_modules + # - /usr/local/cargo/registry/index + # - /usr/local/cargo/registry/cache + - target/debug/deps + - target/debug/build + +stages: + - test + - build + - dependency + +variables: + POSTGRES_DB: 'firefish_db' + POSTGRES_USER: 'firefish' + POSTGRES_PASSWORD: 'password' + POSTGRES_HOST_AUTH_METHOD: 'trust' + DEBIAN_FRONTEND: 'noninteractive' + CARGO_PROFILE_DEV_OPT_LEVEL: '0' + CARGO_PROFILE_DEV_LTO: 'off' + CARGO_PROFILE_DEV_DEBUG: 'none' + +default: + before_script: + - apt-get update && apt-get -y upgrade + - apt-get -y --no-install-recommends install curl + - curl -fsSL 'https://deb.nodesource.com/setup_18.x' | bash - + - apt-get install -y --no-install-recommends build-essential clang mold python3 perl nodejs postgresql-client + - corepack enable + - corepack prepare pnpm@latest --activate + - cp .config/ci.yml .config/default.yml + - cp ci/cargo/config.toml /usr/local/cargo/config.toml + - export PGPASSWORD="${POSTGRES_PASSWORD}" + - psql --host postgres --user "${POSTGRES_USER}" --dbname "${POSTGRES_DB}" --command 'CREATE EXTENSION pgroonga' + +build_test: + stage: test + rules: + - if: $CI_PIPELINE_SOURCE == 'push' || $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + paths: + - packages/**/* + - scripts/**/* + - locales/**/* + - package.json + - pnpm-lock.yaml + - Cargo.toml + - Cargo.lock + script: + - pnpm install --frozen-lockfile + - pnpm run build:debug + - pnpm run migrate + +container_image_build: + stage: build + image: docker.io/debian:bookworm-slim + services: [] + rules: + - if: $CI_COMMIT_BRANCH == 'develop' + changes: + paths: + - packages/**/* + - locales/**/* + - scripts/copy-assets.mjs + - package.json + - pnpm-lock.yaml + - Cargo.toml + - Cargo.lock + - Dockerfile + - .dockerignore + before_script: + - apt-get update && apt-get -y upgrade + - apt-get install -y --no-install-recommends buildah ca-certificates fuse-overlayfs + - buildah login --username "${CI_REGISTRY_USER}" --password "${CI_REGISTRY_PASSWORD}" "${CI_REGISTRY}" + - export IMAGE_TAG="${CI_REGISTRY}/${CI_PROJECT_PATH}/develop:not-for-production" + script: + - buildah build --isolation chroot --device /dev/fuse:rw --security-opt seccomp=unconfined --security-opt apparmor=unconfined --cap-add all --tag "${IMAGE_TAG}" --platform linux/amd64 . + - buildah inspect "${IMAGE_TAG}" + - buildah push "${IMAGE_TAG}" + +cargo_unit_test: + stage: test + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' || $CI_COMMIT_BRANCH == 'develop' + changes: + paths: + - packages/backend-rs/**/* + - packages/macro-rs/**/* + - Cargo.toml + - Cargo.lock + - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'main' + when: never + script: + - cargo check --features napi + - pnpm install --frozen-lockfile + - mkdir packages/backend-rs/built + - cp packages/backend-rs/index.js packages/backend-rs/built/index.js + - cp packages/backend-rs/index.d.ts packages/backend-rs/built/index.d.ts + - pnpm --filter='!backend-rs' run build:debug + - cargo test + +cargo_clippy: + stage: test + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + paths: + - packages/backend-rs/**/* + - packages/macro-rs/**/* + - Cargo.toml + - Cargo.lock + - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'main' + when: never + script: + - cargo clippy -- -D warnings + +renovate: + stage: dependency + image: + name: docker.io/renovate/renovate:37-slim + entrypoint: [""] + rules: + - if: $RENOVATE && $CI_PIPELINE_SOURCE == 'schedule' + services: [] + before_script: [] + script: + - renovate --platform gitlab --token "${API_TOKEN}" --endpoint "${CI_SERVER_URL}/api/v4" "${CI_PROJECT_PATH}" diff --git a/COPYING b/COPYING index 0621b4a8e6..96d91510d3 100644 --- a/COPYING +++ b/COPYING @@ -26,10 +26,6 @@ RsaSignature2017 implementation by Transmute Industries Inc License: MIT https://github.com/transmute-industries/RsaSignature2017/blob/master/LICENSE -Machine learning model for sensitive images by Infinite Red, Inc. -License: MIT -https://github.com/infinitered/nsfwjs/blob/master/LICENSE - Chiptune2.js by Simon Gündling License: MIT https://github.com/deskjet/chiptune2.js#license diff --git a/Cargo.lock b/Cargo.lock index 0a1d9aad18..7d90f96896 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -124,6 +124,17 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + [[package]] name = "async-stream" version = "0.3.5" @@ -207,6 +218,7 @@ dependencies = [ "emojis", "idna", "image", + "isahc", "macro_rs", "napi", "napi-build", @@ -218,7 +230,6 @@ dependencies = [ "rand", "redis", "regex", - "reqwest", "rmp-serde", "sea-orm", "serde", @@ -445,6 +456,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +[[package]] +name = "castaway" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" + [[package]] name = "cc" version = "1.0.95" @@ -519,6 +536,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -534,16 +560,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.6" @@ -661,6 +677,37 @@ dependencies = [ "sha3", ] +[[package]] +name = "curl" +version = "0.4.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e2161dd6eba090ff1594084e95fd67aeccf04382ffea77999ea94ed42ec67b6" +dependencies = [ + "curl-sys", + "libc", + "openssl-probe", + "openssl-sys", + "schannel", + "socket2", + "windows-sys 0.52.0", +] + +[[package]] +name = "curl-sys" +version = "0.4.72+curl-8.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29cbdc8314c447d11e8fd156dcdd031d9e02a7a976163e396b548c03153bc9ea" +dependencies = [ + "cc", + "libc", + "libnghttp2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "windows-sys 0.52.0", +] + [[package]] name = "der" version = "0.7.9" @@ -793,6 +840,15 @@ dependencies = [ "zune-inflate", ] +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.0.2" @@ -929,6 +985,21 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-sink" version = "0.3.30" @@ -995,25 +1066,6 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" -[[package]] -name = "h2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "half" version = "2.4.1" @@ -1108,100 +1160,15 @@ dependencies = [ [[package]] name = "http" -version = "1.1.0" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", "itoa", ] -[[package]] -name = "http-body" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "hyper" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tower", - "tower-service", - "tracing", -] - [[package]] name = "iana-time-zone" version = "0.1.60" @@ -1304,6 +1271,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "interpolate_name" version = "0.2.4" @@ -1316,10 +1292,31 @@ dependencies = [ ] [[package]] -name = "ipnet" -version = "2.9.0" +name = "isahc" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9" +dependencies = [ + "async-channel", + "castaway", + "crossbeam-utils", + "curl", + "curl-sys", + "encoding_rs", + "event-listener", + "futures-lite", + "http", + "log", + "mime", + "once_cell", + "polling", + "slab", + "sluice", + "tracing", + "tracing-futures", + "url", + "waker-fn", +] [[package]] name = "itertools" @@ -1417,6 +1414,16 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libnghttp2-sys" +version = "0.1.10+1.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "959c25552127d2e1fa72f0e52548ec04fc386e827ba71a7bd01db46a447dc135" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "libsqlite3-sys" version = "0.27.0" @@ -1428,6 +1435,18 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libz-sys" +version = "1.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -1591,24 +1610,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -1881,6 +1882,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" version = "0.12.2" @@ -2026,6 +2033,22 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -2330,49 +2353,6 @@ dependencies = [ "bytecheck", ] -[[package]] -name = "reqwest" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" -dependencies = [ - "base64 0.22.0", - "bytes", - "encoding_rs", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-tls", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile 2.1.2", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - [[package]] name = "rgb" version = "0.8.37" @@ -2523,22 +2503,6 @@ dependencies = [ "base64 0.21.7", ] -[[package]] -name = "rustls-pemfile" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" -dependencies = [ - "base64 0.22.0", - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" - [[package]] name = "rustls-webpki" version = "0.101.7" @@ -2680,29 +2644,6 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" -[[package]] -name = "security-framework" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "1.0.22" @@ -2749,18 +2690,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - [[package]] name = "serde_yaml" version = "0.9.34+deprecated" @@ -2876,6 +2805,17 @@ dependencies = [ "autocfg", ] +[[package]] +name = "sluice" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5" +dependencies = [ + "async-channel", + "futures-core", + "futures-io", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -2972,7 +2912,7 @@ dependencies = [ "percent-encoding", "rust_decimal", "rustls", - "rustls-pemfile 1.0.4", + "rustls-pemfile", "serde", "serde_json", "sha2", @@ -3229,33 +3169,6 @@ dependencies = [ "syn 2.0.60", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "system-deps" version = "6.2.2" @@ -3288,7 +3201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand", + "fastrand 2.0.2", "rustix", "windows-sys 0.52.0", ] @@ -3410,16 +3323,6 @@ dependencies = [ "syn 2.0.60", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-stream" version = "0.1.15" @@ -3431,20 +3334,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-util" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - [[package]] name = "toml" version = "0.8.12" @@ -3490,34 +3379,6 @@ dependencies = [ "winnow 0.6.7", ] -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - [[package]] name = "tracing" version = "0.1.40" @@ -3551,6 +3412,16 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + [[package]] name = "tracing-log" version = "0.2.0" @@ -3576,12 +3447,6 @@ dependencies = [ "tracing-log", ] -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - [[package]] name = "typenum" version = "1.17.0" @@ -3695,13 +3560,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] -name = "want" -version = "0.3.1" +name = "waker-fn" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "wasi" @@ -3740,18 +3602,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" version = "0.2.92" @@ -3781,16 +3631,6 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" -[[package]] -name = "web-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "webpki-roots" version = "0.25.4" @@ -4001,16 +3841,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - [[package]] name = "wyz" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 74d032aeae..449f9dccb6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ cuid2 = "0.1.2" emojis = "0.6.2" idna = "0.5.0" image = "0.25.1" +isahc = "1.7.2" nom-exif = "1.2.0" once_cell = "1.19.0" openssl = "0.10.64" @@ -27,7 +28,6 @@ quote = "1.0.36" rand = "0.8.5" redis = "0.25.3" regex = "1.10.4" -reqwest = "0.12.4" rmp-serde = "1.2.0" sea-orm = "0.12.15" serde = "1.0.198" diff --git a/Dockerfile b/Dockerfile index d6b80195bb..0106cdb8a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -45,7 +45,7 @@ COPY packages/backend-rs/index.js packages/backend-rs/built/index.js # Copy in the rest of the files to compile COPY . ./ RUN NODE_ENV='production' pnpm run --filter firefish-js build -RUN NODE_ENV='production' pnpm run --recursive --parallel --filter '!backend-rs' --filter '!firefish-js' build && pnpm run gulp +RUN NODE_ENV='production' pnpm run --recursive --parallel --filter '!backend-rs' --filter '!firefish-js' build && pnpm run build:assets # Trim down the dependencies to only those for production RUN find . -path '*/node_modules/*' -delete && pnpm install --prod --frozen-lockfile diff --git a/Makefile b/Makefile index 55c711855c..249a070648 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ export .PHONY: pre-commit -pre-commit: format entities napi-index +pre-commit: format entities napi .PHONY: format format: @@ -11,11 +11,12 @@ format: .PHONY: entities entities: + pnpm --filter=backend run build:debug pnpm run migrate $(MAKE) -C ./packages/backend-rs regenerate-entities -.PHONY: napi-index -napi-index: +.PHONY: napi +napi: $(MAKE) -C ./packages/backend-rs update-index diff --git a/ci/cargo/config.toml b/ci/cargo/config.toml new file mode 100644 index 0000000000..b0de924994 --- /dev/null +++ b/ci/cargo/config.toml @@ -0,0 +1,3 @@ +[target.x86_64-unknown-linux-gnu] +linker = "/usr/bin/clang" +rustflags = ["-C", "link-arg=--ld-path=/usr/bin/mold"] diff --git a/dev/docs/db-container.md b/dev/docs/db-container.md index 61e7b2609e..b4bb73bc77 100644 --- a/dev/docs/db-container.md +++ b/dev/docs/db-container.md @@ -7,6 +7,8 @@ - Node.js - pnpm - Rust toolchain + - Python 3 + - Perl - FFmpeg - Container runtime - [Docker](https://docs.docker.com/get-docker/) @@ -31,7 +33,7 @@ You can refer to [local-installation.md](./local-installation.md) to install the 1. Copy example config file ```sh cp dev/config.example.env dev/config.env - # If you use container runtime other than Docker, you need to modify the "COMPOSE" variable + # If you use container runtime other than Podman, you need to modify the "COMPOSE" variable # vim dev/config.env ``` 1. Create `.config/default.yml` with the following content @@ -51,12 +53,7 @@ You can refer to [local-installation.md](./local-installation.md) to install the host: localhost port: 26379 - logLevel: [ - 'error', - 'success', - 'warning', - 'info' - ] + maxlogLevel: 'debug' # or 'trace' ``` 1. Start database containers ```sh @@ -84,6 +81,19 @@ You can refer to [local-installation.md](./local-installation.md) to install the DONE * [core boot] Now listening on port 3000 on http://localhost:3000 ``` +## Update auto-generated files in `package/backend-rs` + +You need to install `sea-orm-cli` to regenerate database entities. + +```sh +cargo install sea-orm-cli +``` + +```sh +make entities +make napi +``` + ## Reset the environment You can recreate a fresh local Firefish environment by recreating the database containers: diff --git a/dev/docs/local-installation.md b/dev/docs/local-installation.md index 15c7dad7d4..cc32e94198 100644 --- a/dev/docs/local-installation.md +++ b/dev/docs/local-installation.md @@ -141,12 +141,7 @@ sudo apt install ffmpeg host: localhost port: 6379 - logLevel: [ - 'error', - 'success', - 'warning', - 'info' - ] + maxLogLevel: 'debug' # or 'trace' ``` ## 4. Build and start Firefish diff --git a/docs/api-change.md b/docs/api-change.md index d9b7095c7c..5cbf3922d4 100644 --- a/docs/api-change.md +++ b/docs/api-change.md @@ -2,6 +2,14 @@ Breaking changes are indicated by the :warning: icon. +## Unreleased + +- Adding `lang` to the response of `i` and the request parameter of `i/update`. + +## v20240504 + +- :warning: Removed `release` endpoint. + ## v20240424 - Added `antennaLimit` field to the response of `meta` and `admin/meta`, and the request of `admin/update-meta` (optional). diff --git a/docs/changelog.md b/docs/changelog.md index acf5cba712..19bbecaaec 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -5,6 +5,10 @@ Critical security updates are indicated by the :warning: icon. - Server administrators should check [notice-for-admins.md](./notice-for-admins.md) as well. - Third-party client/bot developers may want to check [api-change.md](./api-change.md) as well. +## [v20240504](https://firefish.dev/firefish/firefish/-/merge_requests/10790/commits) + +- Fix bugs + ## :warning: [v20240430](https://firefish.dev/firefish/firefish/-/merge_requests/10781/commits) - Add ability to group similar notifications diff --git a/docs/downgrade.sql b/docs/downgrade.sql index eed0079c3b..8a41b7e36d 100644 --- a/docs/downgrade.sql +++ b/docs/downgrade.sql @@ -1,6 +1,8 @@ BEGIN; DELETE FROM "migrations" WHERE name IN ( + 'AddUserProfileLanguage1714888400293', + 'DropUnusedIndexes1714643926317', 'AlterAkaType1714099399879', 'AddDriveFileUsage1713451569342', 'ConvertCwVarcharToText1713225866247', @@ -25,6 +27,22 @@ DELETE FROM "migrations" WHERE name IN ( 'RemoveNativeUtilsMigration1705877093218' ); +-- drop-unused-indexes +CREATE INDEX "IDX_01f4581f114e0ebd2bbb876f0b" ON "note_reaction" ("createdAt"); +CREATE INDEX "IDX_0610ebcfcfb4a18441a9bcdab2" ON "poll" ("userId"); +CREATE INDEX "IDX_25dfc71b0369b003a4cd434d0b" ON "note" ("attachedFileTypes"); +CREATE INDEX "IDX_2710a55f826ee236ea1a62698f" ON "hashtag" ("mentionedUsersCount"); +CREATE INDEX "IDX_4c02d38a976c3ae132228c6fce" ON "hashtag" ("mentionedRemoteUsersCount"); +CREATE INDEX "IDX_51c063b6a133a9cb87145450f5" ON "note" ("fileIds"); +CREATE INDEX "IDX_54ebcb6d27222913b908d56fd8" ON "note" ("mentions"); +CREATE INDEX "IDX_7fa20a12319c7f6dc3aed98c0a" ON "poll" ("userHost"); +CREATE INDEX "IDX_88937d94d7443d9a99a76fa5c0" ON "note" ("tags"); +CREATE INDEX "IDX_b11a5e627c41d4dc3170f1d370" ON "notification" ("createdAt"); +CREATE INDEX "IDX_c8dfad3b72196dd1d6b5db168a" ON "drive_file" ("createdAt"); +CREATE INDEX "IDX_d57f9030cd3af7f63ffb1c267c" ON "hashtag" ("attachedUsersCount"); +CREATE INDEX "IDX_e5848eac4940934e23dbc17581" ON "drive_file" ("uri"); +CREATE INDEX "IDX_fa99d777623947a5b05f394cae" ON "user" ("tags"); + -- alter-aka-type ALTER TABLE "user" RENAME COLUMN "alsoKnownAs" TO "alsoKnownAsOld"; ALTER TABLE "user" ADD COLUMN "alsoKnownAs" text; @@ -747,9 +765,6 @@ CREATE SEQUENCE public.__chart_day__users_id_seq CACHE 1; ALTER SEQUENCE public.__chart_day__users_id_seq OWNED BY public.__chart_day__users.id; --- drop-user-profile-language -ALTER TABLE "user_profile" ADD COLUMN "lang" character varying(32); - -- emoji-moderator ALTER TABLE "user" DROP COLUMN "emojiModPerm"; DROP TYPE "public"."user_emojimodperm_enum"; diff --git a/docs/install.md b/docs/install.md index d60ad0a707..f13a32d8eb 100644 --- a/docs/install.md +++ b/docs/install.md @@ -24,6 +24,7 @@ Firefish depends on the following software. - `build-essential` on Debian/Ubuntu Linux - `base-devel` on Arch Linux - [Python 3](https://www.python.org/) +- [Perl](https://www.perl.org/) This document shows an example procedure for installing these dependencies and Firefish on Debian 12. Note that there is much room for customizing the server setup; this document merely demonstrates a simple installation. @@ -325,7 +326,7 @@ cd ~/firefish - To add custom locales, place them in the `./custom/locales/` directory. If you name your custom locale the same as an existing locale, it will overwrite it. If you give it a unique name, it will be added to the list. Also make sure that the first part of the filename matches the locale you're basing it on. (Example: `en-FOO.yml`) - To add custom error images, place them in the `./custom/assets/badges` directory, replacing the files already there. - To add custom sounds, place only mp3 files in the `./custom/assets/sounds` directory. -- To update custom assets without rebuilding, just run `pnpm run gulp`. +- To update custom assets without rebuilding, just run `pnpm run build:assets`. - To block ChatGPT, CommonCrawl, or other crawlers from indexing your instance, uncomment the respective rules in `./custom/robots.txt`. ## Tips & Tricks diff --git a/docs/notice-for-admins.md b/docs/notice-for-admins.md index 2ea21bfe85..6f979923ff 100644 --- a/docs/notice-for-admins.md +++ b/docs/notice-for-admins.md @@ -10,24 +10,22 @@ You can control the verbosity of the server log by adding `maxLogLevel` in `.con ### For systemd/pm2 users -Not only Firefish but also Node.js has recently fixed a few security issues: - -- https://nodejs.org/en/blog/vulnerability/april-2024-security-releases -- https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2 - -So, it is highly recommended that you upgrade your Node.js version as well. The new versions are - -- Node v18.20.2 (v18.x LTS) -- Node v20.12.2 (v20.x LTS) -- Node v21.7.3 (v21.x) - -You can check your Node.js version by this command: - -```sh -node --version -``` - -[Node v22](https://nodejs.org/en/blog/announcements/v22-release-announce) was also released several days ago, but we have not yet tested Firefish with this version. +- You need to install Perl to build Firefish. Since Git depends on Perl in many packaging systems, you probably already have Perl installed on your system. You can check the Perl version by this command: + ```sh + perl --version + ``` +- Not only Firefish but also Node.js has recently fixed a few security issues: + - https://nodejs.org/en/blog/vulnerability/april-2024-security-releases + - https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2 + So, it is highly recommended that you upgrade your Node.js version as well. The new versions are + - Node v18.20.2 (v18.x LTS) + - Node v20.12.2 (v20.x LTS) + - Node v21.7.3 (v21.x) + - You can check your Node.js version by this command: + ```sh + node --version + ``` + [Node v22](https://nodejs.org/en/blog/announcements/v22-release-announce) was also released several days ago, but we have not yet tested Firefish with this version. ## v20240413 diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 66f93dabb3..0000000000 --- a/gulpfile.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Gulp tasks - */ - -const fs = require("fs"); -const gulp = require("gulp"); -const replace = require("gulp-replace"); -const terser = require("gulp-terser"); -const cssnano = require("gulp-cssnano"); - -const meta = require("./package.json"); - -gulp.task("copy:backend:views", () => - gulp - .src("./packages/backend/src/server/web/views/**/*") - .pipe(gulp.dest("./packages/backend/built/server/web/views")), -); - -gulp.task("copy:backend:custom", () => - gulp - .src("./custom/assets/**/*") - .pipe(gulp.dest("./packages/backend/assets/")), -); - -gulp.task("copy:client:fonts", () => - gulp - .src("./packages/client/node_modules/three/examples/fonts/**/*") - .pipe(gulp.dest("./built/_client_dist_/fonts/")), -); - -gulp.task("copy:client:locales", async (cb) => { - fs.mkdirSync("./built/_client_dist_/locales", { recursive: true }); - const { default: locales } = await import("./locales/index.mjs"); - - const v = { _version_: meta.version }; - - for (const [lang, locale] of Object.entries(locales)) { - fs.writeFileSync( - `./built/_client_dist_/locales/${lang}.${meta.version}.json`, - JSON.stringify({ ...locale, ...v }), - "utf-8", - ); - } - - cb(); -}); - -gulp.task("build:backend:script", async () => { - const { default: locales } = await import("./locales/index.mjs"); - - return gulp - .src([ - "./packages/backend/src/server/web/boot.js", - "./packages/backend/src/server/web/bios.js", - "./packages/backend/src/server/web/cli.js", - ]) - .pipe(replace("SUPPORTED_LANGS", JSON.stringify(Object.keys(locales)))) - .pipe( - terser({ - toplevel: true, - }), - ) - .pipe(gulp.dest("./packages/backend/built/server/web/")); -}); - -gulp.task("build:backend:style", () => { - return gulp - .src([ - "./packages/backend/src/server/web/style.css", - "./packages/backend/src/server/web/bios.css", - "./packages/backend/src/server/web/cli.css", - ]) - .pipe( - cssnano({ - zindex: false, - }), - ) - .pipe(gulp.dest("./packages/backend/built/server/web/")); -}); - -gulp.task( - "build", - gulp.parallel( - "copy:client:locales", - "copy:backend:views", - "copy:backend:custom", - "build:backend:script", - "build:backend:style", - "copy:client:fonts", - ), -); - -gulp.task("default", gulp.task("build")); - -gulp.task("watch", () => { - gulp.watch( - ["./packages/*/src/**/*"], - { ignoreInitial: false }, - gulp.task("build"), - ); -}); diff --git a/locales/en-US.yml b/locales/en-US.yml index 6244267e5f..11ed94218a 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -766,6 +766,9 @@ confirmToUnclipAlreadyClippedNote: "This post is already part of the \"{name}\" public: "Public" i18nInfo: "Firefish is being translated into various languages by volunteers. You can help at {link}." +i18nServerInfo: "New clients will be in {language} by default." +i18nServerChange: "Use {language} instead." +i18nServerSet: "Use {language} for new clients." manageAccessTokens: "Manage access tokens" accountInfo: "Account Info" notesCount: "Number of posts" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index ef9f9b9bfb..b983f44806 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -685,6 +685,9 @@ unclip: "クリップ解除" confirmToUnclipAlreadyClippedNote: "この投稿はすでにクリップ「{name}」に含まれています。投稿をこのクリップから除外しますか?" public: "公開" i18nInfo: "Firefishは有志によって様々な言語に翻訳されています。{link}で翻訳に協力できます。" +i18nServerInfo: "新しい端末では{language}が既定の言語になります。" +i18nServerChange: "{language}に変更する。" +i18nServerSet: "新しい端末での表示言語を{language}にします。" manageAccessTokens: "アクセストークンの管理" accountInfo: "アカウント情報" notesCount: "投稿の数" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 464f186ea5..f64498e358 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -667,6 +667,9 @@ unclip: "移除便签" confirmToUnclipAlreadyClippedNote: "本帖已包含在便签 \"{name}\" 里。您想要将本帖从该便签中移除吗?" public: "公开" i18nInfo: "Firefish 已经被志愿者们翻译成了各种语言。如果您也有兴趣,可以通过 {link} 帮助翻译。" +i18nServerInfo: "新客户端将默认使用 {language}。" +i18nServerChange: "改为 {language}。" +i18nServerSet: "设定新客户端使用 {language}。" manageAccessTokens: "管理访问令牌" accountInfo: "账号信息" notesCount: "帖子数量" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 5a722933e6..00a7827203 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -661,6 +661,9 @@ unclip: "解除摘錄" confirmToUnclipAlreadyClippedNote: "此貼文已包含在摘錄「{name}」中。 你想將貼文從這個摘錄中排除嗎?" public: "公開" i18nInfo: "Firefish已經被志願者們翻譯成各種語言版本,如果想要幫忙的話,可以進入{link}幫助翻譯。" +i18nServerInfo: "新客戶端將默認使用 {language}。" +i18nServerChange: "改為 {language}。" +i18nServerSet: "設定新客戶端使用 {language}。" manageAccessTokens: "管理存取權杖" accountInfo: "帳戶資訊" notesCount: "貼文數量" diff --git a/package.json b/package.json index 90277975f1..77d8ef91c5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "firefish", - "version": "20240430", + "version": "20240504", "repository": { "type": "git", "url": "https://firefish.dev/firefish/firefish.git" @@ -9,14 +9,15 @@ "private": true, "scripts": { "rebuild": "pnpm run clean && pnpm run build", - "build": "pnpm node ./scripts/build.mjs && pnpm run gulp", + "build": "pnpm node ./scripts/build.mjs && pnpm run build:assets", + "build:assets": "pnpm node ./scripts/copy-assets.mjs", + "build:debug": "pnpm run clean && pnpm node ./scripts/dev-build.mjs && pnpm run build:assets", "start": "pnpm --filter backend run start", - "start:container": "pnpm run gulp && pnpm run migrate && pnpm run start", + "start:container": "pnpm run build:assets && pnpm run migrate && pnpm run start", "start:test": "pnpm --filter backend run start:test", "init": "pnpm run migrate", "migrate": "pnpm --filter backend run migration:run", "revertmigration": "pnpm --filter backend run migration:revert", - "gulp": "gulp build", "watch": "pnpm run dev", "dev": "pnpm node ./scripts/dev.mjs", "dev:staging": "NODE_OPTIONS=--max_old_space_size=3072 NODE_ENV=development pnpm run build && pnpm run start", @@ -24,7 +25,6 @@ "lint:ts": "pnpm --filter !firefish-js -r --parallel run lint", "lint:rs": "cargo clippy --fix --allow-dirty --allow-staged && cargo fmt --all --", "debug": "pnpm run build:debug && pnpm run start", - "build:debug": "pnpm run clean && pnpm node ./scripts/dev-build.mjs && pnpm run gulp", "mocha": "pnpm --filter backend run mocha", "test": "pnpm run test:ts && pnpm run test:rs", "test:ts": "pnpm run mocha", @@ -38,10 +38,6 @@ "clean-all": "pnpm run clean && pnpm run clean-cargo && pnpm run clean-npm" }, "dependencies": { - "gulp": "4.0.2", - "gulp-cssnano": "2.1.3", - "gulp-replace": "1.1.4", - "gulp-terser": "2.1.0", "js-yaml": "4.1.0" }, "devDependencies": { diff --git a/packages/backend-rs/Cargo.toml b/packages/backend-rs/Cargo.toml index c1b511b992..936fc525cf 100644 --- a/packages/backend-rs/Cargo.toml +++ b/packages/backend-rs/Cargo.toml @@ -7,6 +7,7 @@ rust-version = "1.74" [features] default = [] napi = ["dep:napi", "dep:napi-derive"] +ci = [] [lib] crate-type = ["cdylib", "lib"] @@ -25,13 +26,13 @@ cuid2 = { workspace = true } emojis = { workspace = true } idna = { workspace = true } image = { workspace = true } +isahc = { workspace = true } nom-exif = { workspace = true } once_cell = { workspace = true } openssl = { workspace = true, features = ["vendored"] } rand = { workspace = true } redis = { workspace = true } regex = { workspace = true } -reqwest = { workspace = true, features = ["blocking"] } rmp-serde = { workspace = true } sea-orm = { workspace = true, features = ["sqlx-postgres", "runtime-tokio-rustls"] } serde = { workspace = true, features = ["derive"] } diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts index 5b9d0ee894..b161473d9a 100644 --- a/packages/backend-rs/index.d.ts +++ b/packages/backend-rs/index.d.ts @@ -214,19 +214,26 @@ export function stringToAcct(acct: string): Acct export function acctToString(acct: Acct): string export function addNoteToAntenna(antennaId: string, note: Note): void /** - * @param host punycoded instance host - * @returns whether the given host should be blocked -*/ + * Checks if a server is blocked. + * + * ## Argument + * `host` - punycoded instance host + */ export function isBlockedServer(host: string): Promise /** - * @param host punycoded instance host - * @returns whether the given host should be limited -*/ + * Checks if a server is silenced. + * + * ## Argument + * `host` - punycoded instance host + */ export function isSilencedServer(host: string): Promise /** - * @param host punycoded instance host - * @returns whether the given host is allowlisted (this is always true if private mode is disabled) -*/ + * Checks if a server is allowlisted. + * Returns `Ok(true)` if private mode is disabled. + * + * ## Argument + * `host` - punycoded instance host + */ export function isAllowedServer(host: string): Promise /** TODO: handle name collisions better */ export interface NoteLikeForCheckWordMute { @@ -261,6 +268,8 @@ export interface NoteLikeForGetNoteSummary { hasPoll: boolean } export function getNoteSummary(note: NoteLikeForGetNoteSummary): string +export function isSafeUrl(url: string): boolean +export function latestVersion(): Promise export function toMastodonId(firefishId: string): string | null export function fromMastodonId(mastodonId: string): string | null export function fetchMeta(useCache: boolean): Promise @@ -1121,6 +1130,7 @@ export interface UserProfile { preventAiLearning: boolean isIndexable: boolean mutedPatterns: Array + lang: string | null } export interface UserPublickey { userId: string @@ -1147,6 +1157,106 @@ export interface Webhook { latestStatus: number | null } export function initializeRustLogger(): void +export function fetchNodeinfo(host: string): Promise +export function nodeinfo_2_1(): Promise +export function nodeinfo_2_0(): Promise +/** NodeInfo schema version 2.0. https://nodeinfo.diaspora.software/docson/index.html#/ns/schema/2.0 */ +export interface Nodeinfo { + /** The schema version, must be 2.0. */ + version: string + /** Metadata about server software in use. */ + software: Software20 + /** The protocols supported on this server. */ + protocols: Array + /** The third party sites this server can connect to via their application API. */ + services: Services + /** Whether this server allows open self-registration. */ + openRegistrations: boolean + /** Usage statistics for this server. */ + usage: Usage + /** Free form key value pairs for software specific values. Clients should not rely on any specific key present. */ + metadata: Record +} +/** Metadata about server software in use (version 2.0). */ +export interface Software20 { + /** The canonical name of this server software. */ + name: string + /** The version of this server software. */ + version: string +} +export enum Protocol { + Activitypub = 'activitypub', + Buddycloud = 'buddycloud', + Dfrn = 'dfrn', + Diaspora = 'diaspora', + Libertree = 'libertree', + Ostatus = 'ostatus', + Pumpio = 'pumpio', + Tent = 'tent', + Xmpp = 'xmpp', + Zot = 'zot' +} +/** The third party sites this server can connect to via their application API. */ +export interface Services { + /** The third party sites this server can retrieve messages from for combined display with regular traffic. */ + inbound: Array + /** The third party sites this server can publish messages to on the behalf of a user. */ + outbound: Array +} +/** The third party sites this server can retrieve messages from for combined display with regular traffic. */ +export enum Inbound { + Atom1 = 'atom1', + Gnusocial = 'gnusocial', + Imap = 'imap', + Pnut = 'pnut', + Pop3 = 'pop3', + Pumpio = 'pumpio', + Rss2 = 'rss2', + Twitter = 'twitter' +} +/** The third party sites this server can publish messages to on the behalf of a user. */ +export enum Outbound { + Atom1 = 'atom1', + Blogger = 'blogger', + Buddycloud = 'buddycloud', + Diaspora = 'diaspora', + Dreamwidth = 'dreamwidth', + Drupal = 'drupal', + Facebook = 'facebook', + Friendica = 'friendica', + Gnusocial = 'gnusocial', + Google = 'google', + Insanejournal = 'insanejournal', + Libertree = 'libertree', + Linkedin = 'linkedin', + Livejournal = 'livejournal', + Mediagoblin = 'mediagoblin', + Myspace = 'myspace', + Pinterest = 'pinterest', + Pnut = 'pnut', + Posterous = 'posterous', + Pumpio = 'pumpio', + Redmatrix = 'redmatrix', + Rss2 = 'rss2', + Smtp = 'smtp', + Tent = 'tent', + Tumblr = 'tumblr', + Twitter = 'twitter', + Wordpress = 'wordpress', + Xmpp = 'xmpp' +} +/** Usage statistics for this server. */ +export interface Usage { + users: Users + localPosts: number | null + localComments: number | null +} +/** statistics about the users of this server. */ +export interface Users { + total: number | null + activeHalfyear: number | null + activeMonth: number | null +} export function watchNote(watcherId: string, noteAuthorId: string, noteId: string): Promise export function unwatchNote(watcherId: string, noteId: string): Promise export function publishToChannelStream(channelId: string, userId: string): void diff --git a/packages/backend-rs/index.js b/packages/backend-rs/index.js index b351840dfe..0d9938f9ed 100644 --- a/packages/backend-rs/index.js +++ b/packages/backend-rs/index.js @@ -310,7 +310,7 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { SECOND, MINUTE, HOUR, DAY, USER_ONLINE_THRESHOLD, USER_ACTIVE_THRESHOLD, FILE_TYPE_BROWSERSAFE, loadEnv, loadConfig, stringToAcct, acctToString, addNoteToAntenna, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getImageSizeFromUrl, getNoteSummary, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, removeOldAttestationChallenges, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initializeRustLogger, watchNote, unwatchNote, publishToChannelStream, ChatEvent, publishToChatStream, ChatIndexEvent, publishToChatIndexStream, publishToBroadcastStream, publishToGroupChatStream, publishToModerationStream, getTimestamp, genId, genIdAt, secureRndstr } = nativeBinding +const { SECOND, MINUTE, HOUR, DAY, USER_ONLINE_THRESHOLD, USER_ACTIVE_THRESHOLD, FILE_TYPE_BROWSERSAFE, loadEnv, loadConfig, stringToAcct, acctToString, addNoteToAntenna, isBlockedServer, isSilencedServer, isAllowedServer, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, isUnicodeEmoji, sqlLikeEscape, safeForSql, formatMilliseconds, getImageSizeFromUrl, getNoteSummary, isSafeUrl, latestVersion, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, decodeReaction, countReactions, toDbReaction, removeOldAttestationChallenges, AntennaSrcEnum, DriveFileUsageHintEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initializeRustLogger, fetchNodeinfo, nodeinfo_2_1, nodeinfo_2_0, Protocol, Inbound, Outbound, watchNote, unwatchNote, publishToChannelStream, ChatEvent, publishToChatStream, ChatIndexEvent, publishToChatIndexStream, publishToBroadcastStream, publishToGroupChatStream, publishToModerationStream, getTimestamp, genId, genIdAt, secureRndstr } = nativeBinding module.exports.SECOND = SECOND module.exports.MINUTE = MINUTE @@ -339,6 +339,8 @@ module.exports.safeForSql = safeForSql module.exports.formatMilliseconds = formatMilliseconds module.exports.getImageSizeFromUrl = getImageSizeFromUrl module.exports.getNoteSummary = getNoteSummary +module.exports.isSafeUrl = isSafeUrl +module.exports.latestVersion = latestVersion module.exports.toMastodonId = toMastodonId module.exports.fromMastodonId = fromMastodonId module.exports.fetchMeta = fetchMeta @@ -363,6 +365,12 @@ module.exports.UserEmojimodpermEnum = UserEmojimodpermEnum module.exports.UserProfileFfvisibilityEnum = UserProfileFfvisibilityEnum module.exports.UserProfileMutingnotificationtypesEnum = UserProfileMutingnotificationtypesEnum module.exports.initializeRustLogger = initializeRustLogger +module.exports.fetchNodeinfo = fetchNodeinfo +module.exports.nodeinfo_2_1 = nodeinfo_2_1 +module.exports.nodeinfo_2_0 = nodeinfo_2_0 +module.exports.Protocol = Protocol +module.exports.Inbound = Inbound +module.exports.Outbound = Outbound module.exports.watchNote = watchNote module.exports.unwatchNote = unwatchNote module.exports.publishToChannelStream = publishToChannelStream diff --git a/packages/backend-rs/src/database/cache.rs b/packages/backend-rs/src/database/cache.rs new file mode 100644 index 0000000000..5b29de46b2 --- /dev/null +++ b/packages/backend-rs/src/database/cache.rs @@ -0,0 +1,290 @@ +use crate::database::{redis_conn, redis_key}; +use redis::{Commands, RedisError}; +use serde::{Deserialize, Serialize}; + +#[derive(strum::Display, Debug)] +pub enum Category { + #[strum(serialize = "fetchUrl")] + FetchUrl, + #[cfg(test)] + #[strum(serialize = "usedOnlyForTesting")] + Test, +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Redis error: {0}")] + RedisError(#[from] RedisError), + #[error("Data serialization error: {0}")] + SerializeError(#[from] rmp_serde::encode::Error), + #[error("Data deserialization error: {0}")] + DeserializeError(#[from] rmp_serde::decode::Error), +} + +#[inline] +fn prefix_key(key: &str) -> String { + redis_key(format!("cache:{}", key)) +} + +#[inline] +fn categorize(category: Category, key: &str) -> String { + format!("{}:{}", category, key) +} + +#[inline] +fn wildcard(category: Category) -> String { + prefix_key(&categorize(category, "*")) +} + +/// Sets a Redis cache. +/// +/// This overwrites the exsisting cache with the same key. +/// +/// ## Arguments +/// +/// * `key` - key (will be prefixed automatically) +/// * `value` - (de)serializable value +/// * `expire_seconds` - TTL +/// +/// ## Example +/// +/// ``` +/// use backend_rs::database::cache; +/// let key = "apple"; +/// let data = "I want to cache this string".to_string(); +/// +/// // caches the data for 10 seconds +/// cache::set(key, &data, 10); +/// +/// // get the cache +/// let cached_data = cache::get::(key).unwrap(); +/// assert_eq!(data, cached_data.unwrap()); +/// ``` +pub fn set Deserialize<'a> + Serialize>( + key: &str, + value: &V, + expire_seconds: u64, +) -> Result<(), Error> { + redis_conn()?.set_ex( + prefix_key(key), + rmp_serde::encode::to_vec(&value)?, + expire_seconds, + )?; + Ok(()) +} + +/// Gets a Redis cache. +/// +/// If the Redis connection is fine, this returns `Ok(data)` where `data` +/// is the cached value. Returns `Ok(None)` if there is no value corresponding to `key`. +/// +/// ## Arguments +/// +/// * `key` - key (will be prefixed automatically) +/// +/// ## Example +/// +/// ``` +/// use backend_rs::database::cache; +/// +/// let key = "banana"; +/// let data = "I want to cache this string".to_string(); +/// +/// // set cache +/// cache::set(key, &data, 10).unwrap(); +/// +/// // get cache +/// let cached_data = cache::get::(key).unwrap(); +/// assert_eq!(data, cached_data.unwrap()); +/// +/// // get nonexistent (or expired) cache +/// let no_cache = cache::get::("nonexistent").unwrap(); +/// assert!(no_cache.is_none()); +/// ``` +pub fn get Deserialize<'a> + Serialize>(key: &str) -> Result, Error> { + let serialized_value: Option> = redis_conn()?.get(prefix_key(key))?; + Ok(match serialized_value { + Some(v) => Some(rmp_serde::from_slice::(v.as_ref())?), + None => None, + }) +} + +/// Deletes a Redis cache. +/// +/// If the Redis connection is fine, this returns `Ok(())` +/// regardless of whether the cache exists. +/// +/// ## Arguments +/// +/// * `key` - key (will be prefixed automatically) +/// +/// ## Example +/// +/// ``` +/// use backend_rs::database::cache::{set, get, delete}; +/// +/// let key = "chocolate"; +/// let value = "I want to cache this string".to_string(); +/// +/// // set cache +/// set(key, &value, 10).unwrap(); +/// +/// // delete the cache +/// delete("foo").unwrap(); +/// delete("nonexistent").unwrap(); // this is okay +/// +/// // the cache is gone +/// let cached_value = get::("foo").unwrap(); +/// assert!(cached_value.is_none()); +/// ``` +pub fn delete(key: &str) -> Result<(), Error> { + Ok(redis_conn()?.del(prefix_key(key))?) +} + +/// Sets a Redis cache under a `category`. +/// +/// The usage is the same as [set], except that you need to +/// use [get_one] and [delete_one] to get/delete the cache. +/// +/// ## Arguments +/// +/// * `category` - one of [Category] +/// * `key` - key (will be prefixed automatically) +/// * `value` - (de)serializable value +/// * `expire_seconds` - TTL +pub fn set_one Deserialize<'a> + Serialize>( + category: Category, + key: &str, + value: &V, + expire_seconds: u64, +) -> Result<(), Error> { + set(&categorize(category, key), value, expire_seconds) +} + +/// Gets a Redis cache under a `category`. +/// +/// The usage is basically the same as [get]. +/// +/// ## Arguments +/// +/// * `category` - one of [Category] +/// * `key` - key (will be prefixed automatically) +pub fn get_one Deserialize<'a> + Serialize>( + category: Category, + key: &str, +) -> Result, Error> { + get(&categorize(category, key)) +} + +/// Deletes a Redis cache under a `category`. +/// +/// The usage is basically the same as [delete]. +/// +/// ## Arguments +/// +/// * `category` - one of [Category] +/// * `key` - key (will be prefixed automatically) +pub fn delete_one(category: Category, key: &str) -> Result<(), Error> { + delete(&categorize(category, key)) +} + +/// Deletes all Redis caches under a `category`. +/// +/// ## Arguments +/// +/// * `category` - one of [Category] +pub fn delete_all(category: Category) -> Result<(), Error> { + let mut redis = redis_conn()?; + let keys: Vec> = redis.keys(wildcard(category))?; + + if !keys.is_empty() { + redis.del(keys)? + } + + Ok(()) +} + +// TODO: set_all(), get_all() + +#[cfg(test)] +mod unit_test { + use crate::database::cache::delete_one; + + use super::{delete_all, get, get_one, set, set_one, Category::Test}; + use pretty_assertions::assert_eq; + + #[test] + fn set_get_expire() { + #[derive(serde::Deserialize, serde::Serialize, PartialEq, Debug)] + struct Data { + id: u32, + kind: String, + } + + let key_1 = "CARGO_TEST_CACHE_KEY_1"; + let value_1: Vec = vec![1, 2, 3, 4, 5]; + + let key_2 = "CARGO_TEST_CACHE_KEY_2"; + let value_2 = "Hello fedizens".to_string(); + + let key_3 = "CARGO_TEST_CACHE_KEY_3"; + let value_3 = Data { + id: 1000000007, + kind: "prime number".to_string(), + }; + + set(key_1, &value_1, 1).unwrap(); + set(key_2, &value_2, 1).unwrap(); + set(key_3, &value_3, 1).unwrap(); + + let cached_value_1: Vec = get(key_1).unwrap().unwrap(); + let cached_value_2: String = get(key_2).unwrap().unwrap(); + let cached_value_3: Data = get(key_3).unwrap().unwrap(); + + assert_eq!(value_1, cached_value_1); + assert_eq!(value_2, cached_value_2); + assert_eq!(value_3, cached_value_3); + + // wait for the cache to expire + std::thread::sleep(std::time::Duration::from_millis(1100)); + + let expired_value_1: Option> = get(key_1).unwrap(); + let expired_value_2: Option> = get(key_2).unwrap(); + let expired_value_3: Option> = get(key_3).unwrap(); + + assert!(expired_value_1.is_none()); + assert!(expired_value_2.is_none()); + assert!(expired_value_3.is_none()); + } + + #[test] + fn use_category() { + let key_1 = "fire"; + let key_2 = "fish"; + let key_3 = "awawa"; + + let value_1 = "hello".to_string(); + let value_2 = 998244353u32; + let value_3 = 'あ'; + + set_one(Test, key_1, &value_1, 5 * 60).unwrap(); + set_one(Test, key_2, &value_2, 5 * 60).unwrap(); + set_one(Test, key_3, &value_3, 5 * 60).unwrap(); + + assert_eq!(get_one::(Test, key_1).unwrap().unwrap(), value_1); + assert_eq!(get_one::(Test, key_2).unwrap().unwrap(), value_2); + assert_eq!(get_one::(Test, key_3).unwrap().unwrap(), value_3); + + delete_one(Test, key_1).unwrap(); + + assert!(get_one::(Test, key_1).unwrap().is_none()); + assert!(get_one::(Test, key_2).unwrap().is_some()); + assert!(get_one::(Test, key_3).unwrap().is_some()); + + delete_all(Test).unwrap(); + + assert!(get_one::(Test, key_1).unwrap().is_none()); + assert!(get_one::(Test, key_2).unwrap().is_none()); + assert!(get_one::(Test, key_3).unwrap().is_none()); + } +} diff --git a/packages/backend-rs/src/database/mod.rs b/packages/backend-rs/src/database/mod.rs index 7a6277068b..f657a540af 100644 --- a/packages/backend-rs/src/database/mod.rs +++ b/packages/backend-rs/src/database/mod.rs @@ -2,5 +2,6 @@ pub use postgresql::db_conn; pub use redis::key as redis_key; pub use redis::redis_conn; +pub mod cache; pub mod postgresql; pub mod redis; diff --git a/packages/backend-rs/src/misc/check_server_block.rs b/packages/backend-rs/src/misc/check_server_block.rs index b5e262aa87..bb7f40078a 100644 --- a/packages/backend-rs/src/misc/check_server_block.rs +++ b/packages/backend-rs/src/misc/check_server_block.rs @@ -1,10 +1,10 @@ use crate::misc::meta::fetch_meta; use sea_orm::DbErr; -/** - * @param host punycoded instance host - * @returns whether the given host should be blocked - */ +/// Checks if a server is blocked. +/// +/// ## Argument +/// `host` - punycoded instance host #[crate::export] pub async fn is_blocked_server(host: &str) -> Result { Ok(fetch_meta(true) @@ -16,10 +16,10 @@ pub async fn is_blocked_server(host: &str) -> Result { })) } -/** - * @param host punycoded instance host - * @returns whether the given host should be limited - */ +/// Checks if a server is silenced. +/// +/// ## Argument +/// `host` - punycoded instance host #[crate::export] pub async fn is_silenced_server(host: &str) -> Result { Ok(fetch_meta(true) @@ -31,10 +31,11 @@ pub async fn is_silenced_server(host: &str) -> Result { })) } -/** - * @param host punycoded instance host - * @returns whether the given host is allowlisted (this is always true if private mode is disabled) - */ +/// Checks if a server is allowlisted. +/// Returns `Ok(true)` if private mode is disabled. +/// +/// ## Argument +/// `host` - punycoded instance host #[crate::export] pub async fn is_allowed_server(host: &str) -> Result { let meta = fetch_meta(true).await?; diff --git a/packages/backend-rs/src/misc/get_image_size.rs b/packages/backend-rs/src/misc/get_image_size.rs index 9c55846424..60cf84aec1 100644 --- a/packages/backend-rs/src/misc/get_image_size.rs +++ b/packages/backend-rs/src/misc/get_image_size.rs @@ -1,6 +1,7 @@ -use crate::misc::redis_cache::{get_cache, set_cache, CacheError}; +use crate::database::cache; use crate::util::http_client; use image::{io::Reader, ImageError, ImageFormat}; +use isahc::ReadResponseExt; use nom_exif::{parse_jpeg_exif, EntryValue, ExifTag}; use std::io::Cursor; use tokio::sync::Mutex; @@ -8,9 +9,13 @@ use tokio::sync::Mutex; #[derive(thiserror::Error, Debug)] pub enum Error { #[error("Redis cache error: {0}")] - CacheErr(#[from] CacheError), - #[error("Reqwest error: {0}")] - ReqwestErr(#[from] reqwest::Error), + CacheErr(#[from] cache::Error), + #[error("HTTP client aquisition error: {0}")] + HttpClientErr(#[from] http_client::Error), + #[error("Isahc error: {0}")] + IsahcErr(#[from] isahc::Error), + #[error("HTTP error: {0}")] + HttpErr(String), #[error("Image decoding error: {0}")] ImageErr(#[from] ImageError), #[error("Image decoding error: {0}")] @@ -50,11 +55,10 @@ pub async fn get_image_size_from_url(url: &str) -> Result { { let _ = MTX_GUARD.lock().await; - let key = format!("fetchImage:{}", url); - attempted = get_cache::(&key)?.is_some(); + attempted = cache::get_one::(cache::Category::FetchUrl, url)?.is_some(); if !attempted { - set_cache(&key, &true, 10 * 60)?; + cache::set_one(cache::Category::FetchUrl, url, &true, 10 * 60)?; } } @@ -65,7 +69,16 @@ pub async fn get_image_size_from_url(url: &str) -> Result { tracing::info!("retrieving image size from {}", url); - let image_bytes = http_client()?.get(url).send().await?.bytes().await?; + let mut response = http_client::client()?.get(url)?; + + if !response.status().is_success() { + tracing::info!("status: {}", response.status()); + tracing::debug!("response body: {:#?}", response.body()); + return Err(Error::HttpErr(format!("Failed to get image from {}", url))); + } + + let image_bytes = response.bytes()?; + let reader = Reader::new(Cursor::new(&image_bytes)).with_guessed_format()?; let format = reader.format(); @@ -109,7 +122,7 @@ pub async fn get_image_size_from_url(url: &str) -> Result { #[cfg(test)] mod unit_test { use super::{get_image_size_from_url, ImageSize}; - use crate::misc::redis_cache::delete_cache; + use crate::database::cache; use pretty_assertions::assert_eq; #[tokio::test] @@ -124,17 +137,8 @@ mod unit_test { let gif_url = "https://firefish.dev/firefish/firefish/-/raw/b9c3dfbd3d473cb2cee20c467eeae780bc401271/packages/backend/test/resources/anime.gif"; let mp3_url = "https://firefish.dev/firefish/firefish/-/blob/5891a90f71a8b9d5ea99c683ade7e485c685d642/packages/backend/assets/sounds/aisha/1.mp3"; - // Delete caches in case you run this test multiple times - // (should be disabled in CI tasks) - delete_cache(&format!("fetchImage:{}", png_url_1)).unwrap(); - delete_cache(&format!("fetchImage:{}", png_url_2)).unwrap(); - delete_cache(&format!("fetchImage:{}", png_url_3)).unwrap(); - delete_cache(&format!("fetchImage:{}", rotated_jpeg_url)).unwrap(); - delete_cache(&format!("fetchImage:{}", webp_url_1)).unwrap(); - delete_cache(&format!("fetchImage:{}", webp_url_2)).unwrap(); - delete_cache(&format!("fetchImage:{}", ico_url)).unwrap(); - delete_cache(&format!("fetchImage:{}", gif_url)).unwrap(); - delete_cache(&format!("fetchImage:{}", mp3_url)).unwrap(); + // delete caches in case you run this test multiple times + cache::delete_all(cache::Category::FetchUrl).unwrap(); let png_size_1 = ImageSize { width: 1024, @@ -197,4 +201,15 @@ mod unit_test { assert_eq!(gif_size, get_image_size_from_url(gif_url).await.unwrap()); assert!(get_image_size_from_url(mp3_url).await.is_err()); } + + #[tokio::test] + async fn too_many_attempts() { + let url = "https://firefish.dev/firefish/firefish/-/raw/5891a90f71a8b9d5ea99c683ade7e485c685d642/packages/backend/assets/splash.png"; + + // delete caches in case you run this test multiple times + cache::delete_one(cache::Category::FetchUrl, url).unwrap(); + + assert!(get_image_size_from_url(url).await.is_ok()); + assert!(get_image_size_from_url(url).await.is_err()); + } } diff --git a/packages/backend-rs/src/misc/is_safe_url.rs b/packages/backend-rs/src/misc/is_safe_url.rs new file mode 100644 index 0000000000..2600366ab5 --- /dev/null +++ b/packages/backend-rs/src/misc/is_safe_url.rs @@ -0,0 +1,34 @@ +#[crate::export] +pub fn is_safe_url(url: &str) -> bool { + if let Ok(url) = url.parse::() { + if url.host_str().unwrap_or_default() == "unix" + || !["http", "https"].contains(&url.scheme()) + || ![None, Some(80), Some(443)].contains(&url.port()) + { + return false; + } + true + } else { + false + } +} + +#[cfg(test)] +mod unit_test { + use super::is_safe_url; + + #[test] + fn safe_url() { + assert!(is_safe_url("http://firefish.dev/firefish/firefish")); + assert!(is_safe_url("https://firefish.dev/firefish/firefish")); + assert!(is_safe_url("http://firefish.dev:80/firefish/firefish")); + assert!(is_safe_url("https://firefish.dev:80/firefish/firefish")); + assert!(is_safe_url("http://firefish.dev:443/firefish/firefish")); + assert!(is_safe_url("https://firefish.dev:443/firefish/firefish")); + assert!(!is_safe_url("https://unix/firefish/firefish")); + assert!(!is_safe_url("https://firefish.dev:35/firefish/firefish")); + assert!(!is_safe_url("ftp://firefish.dev/firefish/firefish")); + assert!(!is_safe_url("nyaa")); + assert!(!is_safe_url("")); + } +} diff --git a/packages/backend-rs/src/misc/latest_version.rs b/packages/backend-rs/src/misc/latest_version.rs new file mode 100644 index 0000000000..cea6901bbe --- /dev/null +++ b/packages/backend-rs/src/misc/latest_version.rs @@ -0,0 +1,108 @@ +use crate::database::cache; +use crate::util::http_client; +use isahc::ReadResponseExt; +use serde::{Deserialize, Serialize}; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Cache error: {0}")] + CacheErr(#[from] cache::Error), + #[error("Isahc error: {0}")] + IsahcErr(#[from] isahc::Error), + #[error("HTTP client aquisition error: {0}")] + HttpClientErr(#[from] http_client::Error), + #[error("HTTP error: {0}")] + HttpErr(String), + #[error("Response parsing error: {0}")] + IoErr(#[from] std::io::Error), + #[error("Failed to deserialize JSON: {0}")] + JsonErr(#[from] serde_json::Error), +} + +const UPSTREAM_PACKAGE_JSON_URL: &str = + "https://firefish.dev/firefish/firefish/-/raw/main/package.json"; + +async fn get_latest_version() -> Result { + #[derive(Debug, Deserialize, Serialize)] + struct Response { + version: String, + } + + let mut response = http_client::client()?.get(UPSTREAM_PACKAGE_JSON_URL)?; + + if !response.status().is_success() { + tracing::info!("status: {}", response.status()); + tracing::debug!("response body: {:#?}", response.body()); + return Err(Error::HttpErr( + "Failed to fetch version from Firefish GitLab".to_string(), + )); + } + + let res_parsed: Response = serde_json::from_str(&response.text()?)?; + + Ok(res_parsed.version) +} + +#[crate::export] +pub async fn latest_version() -> Result { + let version: Option = + cache::get_one(cache::Category::FetchUrl, UPSTREAM_PACKAGE_JSON_URL)?; + + if let Some(v) = version { + tracing::trace!("use cached value: {}", v); + Ok(v) + } else { + tracing::trace!("cache is expired, fetching the latest version"); + let fetched_version = get_latest_version().await?; + tracing::trace!("fetched value: {}", fetched_version); + + cache::set_one( + cache::Category::FetchUrl, + UPSTREAM_PACKAGE_JSON_URL, + &fetched_version, + 3 * 60 * 60, + )?; + Ok(fetched_version) + } +} + +#[cfg(test)] +mod unit_test { + use super::{latest_version, UPSTREAM_PACKAGE_JSON_URL}; + use crate::database::cache; + + fn validate_version(version: String) { + // version: YYYYMMDD or YYYYMMDD-X + assert!(version.len() >= 8); + assert!(version[..8].chars().all(|c| c.is_ascii_digit())); + + // YYYY + assert!(&version[..4] >= "2024"); + + // MM + assert!(&version[4..6] >= "01"); + assert!(&version[4..6] <= "12"); + + // DD + assert!(&version[6..8] >= "01"); + assert!(&version[6..8] <= "31"); + + // -X + if version.len() > 8 { + assert!(version.chars().nth(8).unwrap() == '-'); + assert!(version[9..].chars().all(|c| c.is_ascii_digit())); + } + } + + #[tokio::test] + async fn check_version() { + // delete caches in case you run this test multiple times + cache::delete_one(cache::Category::FetchUrl, UPSTREAM_PACKAGE_JSON_URL).unwrap(); + + // fetch from firefish.dev + validate_version(latest_version().await.unwrap()); + + // use cache + validate_version(latest_version().await.unwrap()); + } +} diff --git a/packages/backend-rs/src/misc/mod.rs b/packages/backend-rs/src/misc/mod.rs index 0ba15dc8e4..d0575c1282 100644 --- a/packages/backend-rs/src/misc/mod.rs +++ b/packages/backend-rs/src/misc/mod.rs @@ -8,10 +8,11 @@ pub mod escape_sql; pub mod format_milliseconds; pub mod get_image_size; pub mod get_note_summary; +pub mod is_safe_url; +pub mod latest_version; pub mod mastodon_id; pub mod meta; pub mod nyaify; pub mod password; pub mod reaction; -pub mod redis_cache; pub mod remove_old_attestation_challenges; diff --git a/packages/backend-rs/src/misc/redis_cache.rs b/packages/backend-rs/src/misc/redis_cache.rs deleted file mode 100644 index 81ac840b8d..0000000000 --- a/packages/backend-rs/src/misc/redis_cache.rs +++ /dev/null @@ -1,94 +0,0 @@ -use crate::database::{redis_conn, redis_key}; -use redis::{Commands, RedisError}; -use serde::{Deserialize, Serialize}; - -#[derive(thiserror::Error, Debug)] -pub enum CacheError { - #[error("Redis error: {0}")] - RedisError(#[from] RedisError), - #[error("Data serialization error: {0}")] - SerializeError(#[from] rmp_serde::encode::Error), - #[error("Data deserialization error: {0}")] - DeserializeError(#[from] rmp_serde::decode::Error), -} - -fn prefix_key(key: &str) -> String { - redis_key(format!("cache:{}", key)) -} - -pub fn set_cache Deserialize<'a> + Serialize>( - key: &str, - value: &V, - expire_seconds: u64, -) -> Result<(), CacheError> { - redis_conn()?.set_ex( - prefix_key(key), - rmp_serde::encode::to_vec(&value)?, - expire_seconds, - )?; - Ok(()) -} - -pub fn get_cache Deserialize<'a> + Serialize>( - key: &str, -) -> Result, CacheError> { - let serialized_value: Option> = redis_conn()?.get(prefix_key(key))?; - Ok(match serialized_value { - Some(v) => Some(rmp_serde::from_slice::(v.as_ref())?), - None => None, - }) -} - -pub fn delete_cache(key: &str) -> Result<(), CacheError> { - Ok(redis_conn()?.del(prefix_key(key))?) -} - -#[cfg(test)] -mod unit_test { - use super::{get_cache, set_cache}; - use pretty_assertions::assert_eq; - - #[test] - fn set_get_expire() { - #[derive(serde::Deserialize, serde::Serialize, PartialEq, Debug)] - struct Data { - id: u32, - kind: String, - } - - let key_1 = "CARGO_TEST_CACHE_KEY_1"; - let value_1: Vec = vec![1, 2, 3, 4, 5]; - - let key_2 = "CARGO_TEST_CACHE_KEY_2"; - let value_2 = "Hello fedizens".to_string(); - - let key_3 = "CARGO_TEST_CACHE_KEY_3"; - let value_3 = Data { - id: 1000000007, - kind: "prime number".to_string(), - }; - - set_cache(key_1, &value_1, 1).unwrap(); - set_cache(key_2, &value_2, 1).unwrap(); - set_cache(key_3, &value_3, 1).unwrap(); - - let cached_value_1: Vec = get_cache(key_1).unwrap().unwrap(); - let cached_value_2: String = get_cache(key_2).unwrap().unwrap(); - let cached_value_3: Data = get_cache(key_3).unwrap().unwrap(); - - assert_eq!(value_1, cached_value_1); - assert_eq!(value_2, cached_value_2); - assert_eq!(value_3, cached_value_3); - - // wait for the cache to expire - std::thread::sleep(std::time::Duration::from_millis(1100)); - - let expired_value_1: Option> = get_cache(key_1).unwrap(); - let expired_value_2: Option> = get_cache(key_2).unwrap(); - let expired_value_3: Option> = get_cache(key_3).unwrap(); - - assert!(expired_value_1.is_none()); - assert!(expired_value_2.is_none()); - assert!(expired_value_3.is_none()); - } -} diff --git a/packages/backend-rs/src/model/entity/user_profile.rs b/packages/backend-rs/src/model/entity/user_profile.rs index 644817aa8d..d461b11292 100644 --- a/packages/backend-rs/src/model/entity/user_profile.rs +++ b/packages/backend-rs/src/model/entity/user_profile.rs @@ -78,6 +78,7 @@ pub struct Model { pub is_indexable: bool, #[sea_orm(column_name = "mutedPatterns")] pub muted_patterns: Vec, + pub lang: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] diff --git a/packages/backend-rs/src/service/mod.rs b/packages/backend-rs/src/service/mod.rs index 0a2644857f..f755f22b4b 100644 --- a/packages/backend-rs/src/service/mod.rs +++ b/packages/backend-rs/src/service/mod.rs @@ -1,3 +1,4 @@ pub mod log; +pub mod nodeinfo; pub mod note; pub mod stream; diff --git a/packages/backend-rs/src/service/nodeinfo/fetch.rs b/packages/backend-rs/src/service/nodeinfo/fetch.rs new file mode 100644 index 0000000000..8177663394 --- /dev/null +++ b/packages/backend-rs/src/service/nodeinfo/fetch.rs @@ -0,0 +1,161 @@ +use crate::service::nodeinfo::schema::*; +use crate::util::http_client; +use isahc::AsyncReadResponseExt; +use serde::{Deserialize, Serialize}; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Http client aquisition error: {0}")] + HttpClientErr(#[from] http_client::Error), + #[error("Http error: {0}")] + HttpErr(#[from] isahc::Error), + #[error("Bad status: {0}")] + BadStatus(String), + #[error("Failed to parse response body as text: {0}")] + ResponseErr(#[from] std::io::Error), + #[error("Failed to parse response body as json: {0}")] + JsonErr(#[from] serde_json::Error), + #[error("No nodeinfo provided")] + MissingNodeinfo, +} + +#[derive(Deserialize, Serialize, Debug)] +pub struct NodeinfoLinks { + links: Vec, +} + +#[derive(Deserialize, Serialize, Debug)] +pub struct NodeinfoLink { + rel: String, + href: String, +} + +#[inline] +fn wellknown_nodeinfo_url(host: &str) -> String { + format!("https://{}/.well-known/nodeinfo", host) +} + +async fn fetch_nodeinfo_links(host: &str) -> Result { + let client = http_client::client()?; + let wellknown_url = wellknown_nodeinfo_url(host); + let mut wellknown_response = client.get_async(&wellknown_url).await?; + + if !wellknown_response.status().is_success() { + tracing::debug!("{:#?}", wellknown_response.body()); + return Err(Error::BadStatus(format!( + "{} returned {}", + wellknown_url, + wellknown_response.status() + ))); + } + + Ok(serde_json::from_str(&wellknown_response.text().await?)?) +} + +fn check_nodeinfo_link(links: NodeinfoLinks) -> Result { + for link in links.links { + if link.rel == "http://nodeinfo.diaspora.software/ns/schema/2.1" + || link.rel == "http://nodeinfo.diaspora.software/ns/schema/2.0" + { + return Ok(link.href); + } + } + + Err(Error::MissingNodeinfo) +} + +async fn fetch_nodeinfo_impl(nodeinfo_link: &str) -> Result { + let client = http_client::client()?; + let mut response = client.get_async(nodeinfo_link).await?; + + if !response.status().is_success() { + tracing::debug!("{:#?}", response.body()); + return Err(Error::BadStatus(format!( + "{} returned {}", + nodeinfo_link, + response.status() + ))); + } + + Ok(serde_json::from_str(&response.text().await?)?) +} + +// for napi export +type Nodeinfo = Nodeinfo20; + +#[crate::export] +pub async fn fetch_nodeinfo(host: &str) -> Result { + tracing::info!("fetching from {}", host); + let links = fetch_nodeinfo_links(host).await?; + let nodeinfo_link = check_nodeinfo_link(links)?; + fetch_nodeinfo_impl(&nodeinfo_link).await +} + +#[cfg(test)] +mod unit_test { + use super::{check_nodeinfo_link, fetch_nodeinfo, NodeinfoLink, NodeinfoLinks}; + use pretty_assertions::assert_eq; + + #[test] + fn test_check_nodeinfo_link() { + let links_1 = NodeinfoLinks { + links: vec![ + NodeinfoLink { + rel: "https://example.com/incorrect/schema/2.0".to_string(), + href: "https://example.com/dummy".to_string(), + }, + NodeinfoLink { + rel: "http://nodeinfo.diaspora.software/ns/schema/2.0".to_string(), + href: "https://example.com/real".to_string(), + }, + ], + }; + assert_eq!( + check_nodeinfo_link(links_1).unwrap(), + "https://example.com/real" + ); + + let links_2 = NodeinfoLinks { + links: vec![ + NodeinfoLink { + rel: "https://example.com/incorrect/schema/2.0".to_string(), + href: "https://example.com/dummy".to_string(), + }, + NodeinfoLink { + rel: "http://nodeinfo.diaspora.software/ns/schema/2.1".to_string(), + href: "https://example.com/real".to_string(), + }, + ], + }; + assert_eq!( + check_nodeinfo_link(links_2).unwrap(), + "https://example.com/real" + ); + + let links_3 = NodeinfoLinks { + links: vec![ + NodeinfoLink { + rel: "https://example.com/incorrect/schema/2.0".to_string(), + href: "https://example.com/dummy/2.0".to_string(), + }, + NodeinfoLink { + rel: "https://example.com/incorrect/schema/2.1".to_string(), + href: "https://example.com/dummy/2.1".to_string(), + }, + ], + }; + check_nodeinfo_link(links_3).expect_err("No nodeinfo"); + } + + #[tokio::test] + async fn test_fetch_nodeinfo() { + assert_eq!( + fetch_nodeinfo("info.firefish.dev") + .await + .unwrap() + .software + .name, + "firefish" + ); + } +} diff --git a/packages/backend-rs/src/service/nodeinfo/generate.rs b/packages/backend-rs/src/service/nodeinfo/generate.rs new file mode 100644 index 0000000000..3385c5a6f8 --- /dev/null +++ b/packages/backend-rs/src/service/nodeinfo/generate.rs @@ -0,0 +1,142 @@ +use crate::config::CONFIG; +use crate::database::cache; +use crate::database::db_conn; +use crate::misc::meta::fetch_meta; +use crate::model::entity::{note, user}; +use crate::service::nodeinfo::schema::*; +use sea_orm::{ColumnTrait, DbErr, EntityTrait, PaginatorTrait, QueryFilter}; +use serde_json::json; +use std::collections::HashMap; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Database error: {0}")] + DbErr(#[from] DbErr), + #[error("Cache error: {0}")] + CacheErr(#[from] cache::Error), + #[error("Failed to serialize nodeinfo to JSON: {0}")] + JsonErr(#[from] serde_json::Error), +} + +async fn statistics() -> Result<(u64, u64, u64, u64), DbErr> { + let db = db_conn().await?; + + let now = chrono::Local::now().naive_local(); + const MONTH: chrono::TimeDelta = chrono::Duration::seconds(2592000000); + const HALF_YEAR: chrono::TimeDelta = chrono::Duration::seconds(15552000000); + + let local_users = user::Entity::find() + .filter(user::Column::Host.is_null()) + .count(db); + let local_active_halfyear = user::Entity::find() + .filter(user::Column::Host.is_null()) + .filter(user::Column::LastActiveDate.gt(now - HALF_YEAR)) + .count(db); + let local_active_month = user::Entity::find() + .filter(user::Column::Host.is_null()) + .filter(user::Column::LastActiveDate.gt(now - MONTH)) + .count(db); + let local_posts = note::Entity::find() + .filter(note::Column::UserHost.is_null()) + .count(db); + + tokio::try_join!( + local_users, + local_active_halfyear, + local_active_month, + local_posts + ) +} + +async fn generate_nodeinfo_2_1() -> Result { + let (local_users, local_active_halfyear, local_active_month, local_posts) = + statistics().await?; + let meta = fetch_meta(true).await?; + let metadata = HashMap::from([ + ( + "nodeName".to_string(), + json!(meta.name.unwrap_or(CONFIG.host.clone())), + ), + ("nodeDescription".to_string(), json!(meta.description)), + ("repositoryUrl".to_string(), json!(meta.repository_url)), + ( + "enableLocalTimeline".to_string(), + json!(!meta.disable_local_timeline), + ), + ( + "enableRecommendedTimeline".to_string(), + json!(!meta.disable_recommended_timeline), + ), + ( + "enableGlobalTimeline".to_string(), + json!(!meta.disable_global_timeline), + ), + ( + "enableGuestTimeline".to_string(), + json!(meta.enable_guest_timeline), + ), + ( + "maintainer".to_string(), + json!({"name":meta.maintainer_name,"email":meta.maintainer_email}), + ), + ("proxyAccountName".to_string(), json!(meta.proxy_account_id)), + ( + "themeColor".to_string(), + json!(meta.theme_color.unwrap_or("#31748f".to_string())), + ), + ]); + + Ok(Nodeinfo21 { + version: "2.1".to_string(), + software: Software21 { + name: "firefish".to_string(), + version: CONFIG.version.clone(), + repository: Some(meta.repository_url), + homepage: Some("https://firefish.dev/firefish/firefish".to_string()), + }, + protocols: vec![Protocol::Activitypub], + services: Services { + inbound: vec![], + outbound: vec![Outbound::Atom1, Outbound::Rss2], + }, + open_registrations: !meta.disable_registration, + usage: Usage { + users: Users { + total: Some(local_users as u32), + active_halfyear: Some(local_active_halfyear as u32), + active_month: Some(local_active_month as u32), + }, + local_posts: Some(local_posts as u32), + local_comments: None, + }, + metadata, + }) +} + +pub async fn nodeinfo_2_1() -> Result { + const NODEINFO_2_1_CACHE_KEY: &str = "nodeinfo_2_1"; + + let cached = cache::get::(NODEINFO_2_1_CACHE_KEY)?; + + if let Some(nodeinfo) = cached { + Ok(nodeinfo) + } else { + let nodeinfo = generate_nodeinfo_2_1().await?; + cache::set(NODEINFO_2_1_CACHE_KEY, &nodeinfo, 60 * 60)?; + Ok(nodeinfo) + } +} + +pub async fn nodeinfo_2_0() -> Result { + Ok(nodeinfo_2_1().await?.into()) +} + +#[crate::export(js_name = "nodeinfo_2_1")] +pub async fn nodeinfo_2_1_as_json() -> Result { + Ok(serde_json::to_value(nodeinfo_2_1().await?)?) +} + +#[crate::export(js_name = "nodeinfo_2_0")] +pub async fn nodeinfo_2_0_as_json() -> Result { + Ok(serde_json::to_value(nodeinfo_2_0().await?)?) +} diff --git a/packages/backend-rs/src/service/nodeinfo/mod.rs b/packages/backend-rs/src/service/nodeinfo/mod.rs new file mode 100644 index 0000000000..e3511ba7e8 --- /dev/null +++ b/packages/backend-rs/src/service/nodeinfo/mod.rs @@ -0,0 +1,3 @@ +pub mod fetch; +pub mod generate; +pub mod schema; diff --git a/packages/backend-rs/src/service/nodeinfo/schema.rs b/packages/backend-rs/src/service/nodeinfo/schema.rs new file mode 100644 index 0000000000..b2a1b67225 --- /dev/null +++ b/packages/backend-rs/src/service/nodeinfo/schema.rs @@ -0,0 +1,263 @@ +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +// TODO: I want to use these macros but they don't work with rmp_serde +// - #[serde(skip_serializing_if = "Option::is_none")] (https://github.com/3Hren/msgpack-rust/issues/86) +// - #[serde(tag = "version", rename = "2.1")] (https://github.com/3Hren/msgpack-rust/issues/318) + +/// NodeInfo schema version 2.1. https://nodeinfo.diaspora.software/docson/index.html#/ns/schema/2.1 +#[derive(Deserialize, Serialize, Debug, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct Nodeinfo21 { + /// The schema version, must be 2.1. + pub version: String, + /// Metadata about server software in use. + pub software: Software21, + /// The protocols supported on this server. + pub protocols: Vec, + /// The third party sites this server can connect to via their application API. + pub services: Services, + /// Whether this server allows open self-registration. + pub open_registrations: bool, + /// Usage statistics for this server. + pub usage: Usage, + /// Free form key value pairs for software specific values. Clients should not rely on any specific key present. + pub metadata: HashMap, +} + +/// NodeInfo schema version 2.0. https://nodeinfo.diaspora.software/docson/index.html#/ns/schema/2.0 +#[derive(Deserialize, Serialize, Debug, PartialEq)] +#[serde(rename_all = "camelCase")] +#[crate::export(object, js_name = "Nodeinfo")] +pub struct Nodeinfo20 { + /// The schema version, must be 2.0. + pub version: String, + /// Metadata about server software in use. + pub software: Software20, + /// The protocols supported on this server. + pub protocols: Vec, + /// The third party sites this server can connect to via their application API. + pub services: Services, + /// Whether this server allows open self-registration. + pub open_registrations: bool, + /// Usage statistics for this server. + pub usage: Usage, + /// Free form key value pairs for software specific values. Clients should not rely on any specific key present. + pub metadata: HashMap, +} + +/// Metadata about server software in use (version 2.1). +#[derive(Deserialize, Serialize, Debug, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct Software21 { + /// The canonical name of this server software. + pub name: String, + /// The version of this server software. + pub version: String, + /// The url of the source code repository of this server software. + pub repository: Option, + /// The url of the homepage of this server software. + pub homepage: Option, +} + +/// Metadata about server software in use (version 2.0). +#[derive(Deserialize, Serialize, Debug, PartialEq)] +#[serde(rename_all = "camelCase")] +#[crate::export(object)] +pub struct Software20 { + /// The canonical name of this server software. + pub name: String, + /// The version of this server software. + pub version: String, +} + +#[derive(Deserialize, Serialize, Debug, PartialEq)] +#[serde(rename_all = "lowercase")] +#[crate::export(string_enum = "lowercase")] +pub enum Protocol { + Activitypub, + Buddycloud, + Dfrn, + Diaspora, + Libertree, + Ostatus, + Pumpio, + Tent, + Xmpp, + Zot, +} + +/// The third party sites this server can connect to via their application API. +#[derive(Deserialize, Serialize, Debug, PartialEq)] +#[serde(rename_all = "camelCase")] +#[crate::export(object)] +pub struct Services { + /// The third party sites this server can retrieve messages from for combined display with regular traffic. + pub inbound: Vec, + /// The third party sites this server can publish messages to on the behalf of a user. + pub outbound: Vec, +} + +/// The third party sites this server can retrieve messages from for combined display with regular traffic. +#[derive(Deserialize, Serialize, Debug, PartialEq)] +#[serde(rename_all = "lowercase")] +#[crate::export(string_enum = "lowercase")] +pub enum Inbound { + #[serde(rename = "atom1.0")] + Atom1, + Gnusocial, + Imap, + Pnut, + #[serde(rename = "pop3")] + Pop3, + Pumpio, + #[serde(rename = "rss2.0")] + Rss2, + Twitter, +} + +/// The third party sites this server can publish messages to on the behalf of a user. +#[derive(Deserialize, Serialize, Debug, PartialEq)] +#[serde(rename_all = "lowercase")] +#[crate::export(string_enum = "lowercase")] +pub enum Outbound { + #[serde(rename = "atom1.0")] + Atom1, + Blogger, + Buddycloud, + Diaspora, + Dreamwidth, + Drupal, + Facebook, + Friendica, + Gnusocial, + Google, + Insanejournal, + Libertree, + Linkedin, + Livejournal, + Mediagoblin, + Myspace, + Pinterest, + Pnut, + Posterous, + Pumpio, + Redmatrix, + #[serde(rename = "rss2.0")] + Rss2, + Smtp, + Tent, + Tumblr, + Twitter, + Wordpress, + Xmpp, +} + +/// Usage statistics for this server. +#[derive(Deserialize, Serialize, Debug, PartialEq)] +#[serde(rename_all = "camelCase")] +#[crate::export(object)] +pub struct Usage { + pub users: Users, + pub local_posts: Option, + pub local_comments: Option, +} + +/// statistics about the users of this server. +#[derive(Deserialize, Serialize, Debug, PartialEq)] +#[serde(rename_all = "camelCase")] +#[crate::export(object)] +pub struct Users { + pub total: Option, + pub active_halfyear: Option, + pub active_month: Option, +} + +impl From for Software20 { + fn from(software: Software21) -> Self { + Self { + name: software.name, + version: software.version, + } + } +} + +impl From for Nodeinfo20 { + fn from(nodeinfo: Nodeinfo21) -> Self { + Self { + version: "2.0".to_string(), + software: nodeinfo.software.into(), + protocols: nodeinfo.protocols, + services: nodeinfo.services, + open_registrations: nodeinfo.open_registrations, + usage: nodeinfo.usage, + metadata: nodeinfo.metadata, + } + } +} + +#[cfg(test)] +mod unit_test { + use super::{Nodeinfo20, Nodeinfo21}; + use pretty_assertions::assert_eq; + + #[test] + fn parse_nodeinfo_2_0() { + let json_str_1 = r#"{"version":"2.0","software":{"name":"mastodon","version":"4.3.0-nightly.2024-04-30"},"protocols":["activitypub"],"services":{"outbound":[],"inbound":[]},"usage":{"users":{"total":1935016,"activeMonth":238223,"activeHalfyear":618795},"localPosts":90175135},"openRegistrations":true,"metadata":{"nodeName":"Mastodon","nodeDescription":"The original server operated by the Mastodon gGmbH non-profit"}}"#; + let parsed_1: Nodeinfo20 = serde_json::from_str(json_str_1).unwrap(); + let serialized_1 = serde_json::to_string(&parsed_1).unwrap(); + let reparsed_1: Nodeinfo20 = serde_json::from_str(&serialized_1).unwrap(); + + assert_eq!(parsed_1, reparsed_1); + assert_eq!(parsed_1.software.name, "mastodon"); + assert_eq!(parsed_1.software.version, "4.3.0-nightly.2024-04-30"); + + let json_str_2 = r#"{"version":"2.0","software":{"name":"peertube","version":"5.0.0"},"protocols":["activitypub"],"services":{"inbound":[],"outbound":["atom1.0","rss2.0"]},"openRegistrations":false,"usage":{"users":{"total":5,"activeMonth":0,"activeHalfyear":2},"localPosts":1018,"localComments":1},"metadata":{"taxonomy":{"postsName":"Videos"},"nodeName":"Blender Video","nodeDescription":"Blender Foundation PeerTube instance.","nodeConfig":{"search":{"remoteUri":{"users":true,"anonymous":false}},"plugin":{"registered":[]},"theme":{"registered":[],"default":"default"},"email":{"enabled":false},"contactForm":{"enabled":true},"transcoding":{"hls":{"enabled":true},"webtorrent":{"enabled":true},"enabledResolutions":[1080]},"live":{"enabled":false,"transcoding":{"enabled":true,"enabledResolutions":[]}},"import":{"videos":{"http":{"enabled":true},"torrent":{"enabled":false}}},"autoBlacklist":{"videos":{"ofUsers":{"enabled":false}}},"avatar":{"file":{"size":{"max":4194304},"extensions":[".png",".jpeg",".jpg",".gif",".webp"]}},"video":{"image":{"extensions":[".png",".jpg",".jpeg",".webp"],"size":{"max":4194304}},"file":{"extensions":[".webm",".ogv",".ogg",".mp4",".mkv",".mov",".qt",".mqv",".m4v",".flv",".f4v",".wmv",".avi",".3gp",".3gpp",".3g2",".3gpp2",".nut",".mts",".m2ts",".mpv",".m2v",".m1v",".mpg",".mpe",".mpeg",".vob",".mxf",".mp3",".wma",".wav",".flac",".aac",".m4a",".ac3"]}},"videoCaption":{"file":{"size":{"max":20971520},"extensions":[".vtt",".srt"]}},"user":{"videoQuota":5368709120,"videoQuotaDaily":-1},"trending":{"videos":{"intervalDays":7}},"tracker":{"enabled":true}}}}"#; + let parsed_2: Nodeinfo20 = serde_json::from_str(json_str_2).unwrap(); + let serialized_2 = serde_json::to_string(&parsed_2).unwrap(); + let reparsed_2: Nodeinfo20 = serde_json::from_str(&serialized_2).unwrap(); + + assert_eq!(parsed_2, reparsed_2); + assert_eq!(parsed_2.software.name, "peertube"); + assert_eq!(parsed_2.software.version, "5.0.0"); + + let json_str_3 = r#"{"metadata":{"nodeName":"pixelfed","software":{"homepage":"https://pixelfed.org","repo":"https://github.com/pixelfed/pixelfed"},"config":{"features":{"timelines":{"local":true,"network":true},"mobile_apis":true,"stories":true,"video":true,"import":{"instagram":false,"mastodon":false,"pixelfed":false},"label":{"covid":{"enabled":false,"org":"visit the WHO website","url":"https://www.who.int/emergencies/diseases/novel-coronavirus-2019/advice-for-public"}},"hls":{"enabled":false}}}},"protocols":["activitypub"],"services":{"inbound":[],"outbound":[]},"software":{"name":"pixelfed","version":"0.12.0"},"usage":{"localPosts":24059868,"localComments":0,"users":{"total":112832,"activeHalfyear":24366,"activeMonth":8921}},"version":"2.0","openRegistrations":true}"#; + let parsed_3: Nodeinfo20 = serde_json::from_str(json_str_3).unwrap(); + let serialized_3 = serde_json::to_string(&parsed_3).unwrap(); + let reparsed_3: Nodeinfo20 = serde_json::from_str(&serialized_3).unwrap(); + + assert_eq!(parsed_3, reparsed_3); + assert_eq!(parsed_3.software.name, "pixelfed"); + assert_eq!(parsed_3.software.version, "0.12.0"); + } + + #[test] + fn parse_nodeinfo_2_1() { + let json_str_1 = r##"{"version":"2.1","software":{"name":"catodon","version":"24.04-dev.2","repository":"https://codeberg.org/catodon/catodon","homepage":"https://codeberg.org/catodon/catodon"},"protocols":["activitypub"],"services":{"inbound":[],"outbound":["atom1.0","rss2.0"]},"openRegistrations":true,"usage":{"users":{"total":294,"activeHalfyear":292,"activeMonth":139},"localPosts":22616,"localComments":0},"metadata":{"nodeName":"Catodon Social","nodeDescription":"🌎 Home of Catodon, a new platform for fedi communities, initially based on Iceshrimp/Firefish/Misskey. Be aware that our first release is not out yet, so things are still experimental.","maintainer":{"name":"admin","email":"redacted@example.com"},"langs":[],"tosUrl":"https://example.com/redacted","repositoryUrl":"https://codeberg.org/catodon/catodon","feedbackUrl":"https://codeberg.org/catodon/catodon/issues","disableRegistration":false,"disableLocalTimeline":false,"disableRecommendedTimeline":true,"disableGlobalTimeline":false,"emailRequiredForSignup":true,"postEditing":true,"postImports":false,"enableHcaptcha":true,"enableRecaptcha":false,"maxNoteTextLength":8000,"maxCaptionTextLength":1500,"enableGithubIntegration":false,"enableDiscordIntegration":false,"enableEmail":true,"themeColor":"#31748f"}}"##; + let parsed_1: Nodeinfo21 = serde_json::from_str(json_str_1).unwrap(); + let serialized_1 = serde_json::to_string(&parsed_1).unwrap(); + let reparsed_1: Nodeinfo21 = serde_json::from_str(&serialized_1).unwrap(); + + assert_eq!(parsed_1, reparsed_1); + assert_eq!(parsed_1.software.name, "catodon"); + assert_eq!(parsed_1.software.version, "24.04-dev.2"); + + let json_str_2 = r#"{"version":"2.1","software":{"name":"meisskey","version":"10.102.699-m544","repository":"https://github.com/mei23/misskey"},"protocols":["activitypub"],"services":{"inbound":[],"outbound":["atom1.0","rss2.0"]},"openRegistrations":true,"usage":{"users":{"total":1123,"activeHalfyear":305,"activeMonth":89},"localPosts":268739,"localComments":0},"metadata":{"nodeName":"meisskey.one","nodeDescription":"ローカルタイムラインのないインスタンスなのだわ\n\n\n[通報・報告 (Report)](https://example.com/redacted)","name":"meisskey.one","description":"ローカルタイムラインのないインスタンスなのだわ\n\n\n[通報・報告 (Report)](https://example.com/redacted)","maintainer":{"name":"redacted","email":"redacted"},"langs":[],"announcements":[{"title":"問題・要望など","text":"問題・要望などは #meisskeyone要望 で投稿してなのだわ"}],"relayActor":"https://example.com/redacted","relays":[],"disableRegistration":false,"disableLocalTimeline":true,"enableRecaptcha":true,"maxNoteTextLength":5000,"enableTwitterIntegration":false,"enableGithubIntegration":false,"enableDiscordIntegration":false,"enableServiceWorker":true,"proxyAccountName":"ghost"}}"#; + let parsed_2: Nodeinfo21 = serde_json::from_str(json_str_2).unwrap(); + let serialized_2 = serde_json::to_string(&parsed_2).unwrap(); + let reparsed_2: Nodeinfo21 = serde_json::from_str(&serialized_2).unwrap(); + + assert_eq!(parsed_2, reparsed_2); + assert_eq!(parsed_2.software.name, "meisskey"); + assert_eq!(parsed_2.software.version, "10.102.699-m544"); + + let json_str_3 = r##"{"metadata":{"enableGlobalTimeline":true,"enableGuestTimeline":false,"enableLocalTimeline":true,"enableRecommendedTimeline":false,"maintainer":{"name":"Firefish dev team"},"nodeDescription":"","nodeName":"Firefish","repositoryUrl":"https://firefish.dev/firefish/firefish","themeColor":"#F25A85"},"openRegistrations":false,"protocols":["activitypub"],"services":{"inbound":[],"outbound":["atom1.0","rss2.0"]},"software":{"homepage":"https://firefish.dev/firefish/firefish","name":"firefish","repository":"https://firefish.dev/firefish/firefish","version":"20240504"},"usage":{"localPosts":23857,"users":{"activeHalfyear":7,"activeMonth":7,"total":9}},"version":"2.1"}"##; + let parsed_3: Nodeinfo20 = serde_json::from_str(json_str_3).unwrap(); + let serialized_3 = serde_json::to_string(&parsed_3).unwrap(); + let reparsed_3: Nodeinfo20 = serde_json::from_str(&serialized_3).unwrap(); + + assert_eq!(parsed_3, reparsed_3); + assert_eq!(parsed_3.software.name, "firefish"); + assert_eq!(parsed_3.software.version, "20240504"); + } +} diff --git a/packages/backend-rs/src/util/http_client.rs b/packages/backend-rs/src/util/http_client.rs index 143e1a2885..97967fcfd1 100644 --- a/packages/backend-rs/src/util/http_client.rs +++ b/packages/backend-rs/src/util/http_client.rs @@ -1,24 +1,34 @@ use crate::config::CONFIG; +use isahc::{config::*, HttpClient}; use once_cell::sync::OnceCell; -use reqwest::{Client, Error, NoProxy, Proxy}; use std::time::Duration; -static CLIENT: OnceCell = OnceCell::new(); +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("Isahc error: {0}")] + IsahcErr(#[from] isahc::Error), + #[error("Url parse error: {0}")] + UrlParseErr(#[from] isahc::http::uri::InvalidUri), +} -pub fn http_client() -> Result { +static CLIENT: OnceCell = OnceCell::new(); + +pub fn client() -> Result { CLIENT .get_or_try_init(|| { - let mut builder = Client::builder().timeout(Duration::from_secs(5)); + let mut builder = HttpClient::builder() + .timeout(Duration::from_secs(10)) + .default_header("user-agent", &CONFIG.user_agent) + .dns_cache(DnsCache::Timeout(Duration::from_secs(60 * 60))); if let Some(proxy_url) = &CONFIG.proxy { - let mut proxy = Proxy::all(proxy_url)?; + builder = builder.proxy(Some(proxy_url.parse()?)); if let Some(proxy_bypass_hosts) = &CONFIG.proxy_bypass_hosts { - proxy = proxy.no_proxy(NoProxy::from_string(&proxy_bypass_hosts.join(","))); + builder = builder.proxy_blacklist(proxy_bypass_hosts); } - builder = builder.proxy(proxy); } - builder.build() + Ok(builder.build()?) }) .cloned() } diff --git a/packages/backend-rs/src/util/mod.rs b/packages/backend-rs/src/util/mod.rs index 13fb8ee64b..93a5fc5ce7 100644 --- a/packages/backend-rs/src/util/mod.rs +++ b/packages/backend-rs/src/util/mod.rs @@ -1,5 +1,3 @@ -pub use http_client::http_client; - pub mod http_client; pub mod id; pub mod random; diff --git a/packages/backend/src/mfm/from-html.ts b/packages/backend/src/mfm/from-html.ts index b0b8957c6d..b00d1441e0 100644 --- a/packages/backend/src/mfm/from-html.ts +++ b/packages/backend/src/mfm/from-html.ts @@ -19,6 +19,13 @@ export function fromHtml(html: string, hashtagNames?: string[]): string { return appendChildren(childNodes, background).join("").trim(); } + /** + * We only exclude text containing asterisks, since the other marks can almost be considered intentionally used. + */ + function escapeAmbiguousMfmMarks(text: string) { + return text.includes("*") ? `${text}` : text; + } + /** * Get only the text, ignoring all formatting inside * @param node @@ -62,7 +69,7 @@ export function fromHtml(html: string, hashtagNames?: string[]): string { background = "", ): (string | string[])[] { if (treeAdapter.isTextNode(node)) { - return [node.value]; + return [escapeAmbiguousMfmMarks(node.value)]; } // Skip comment or document type node diff --git a/packages/backend/src/migration/1714643926317-drop-unused-indexes.ts b/packages/backend/src/migration/1714643926317-drop-unused-indexes.ts new file mode 100644 index 0000000000..c4df055c82 --- /dev/null +++ b/packages/backend/src/migration/1714643926317-drop-unused-indexes.ts @@ -0,0 +1,65 @@ +import type { MigrationInterface, QueryRunner } from "typeorm"; + +export class DropUnusedIndexes1714643926317 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_01f4581f114e0ebd2bbb876f0b"`); + await queryRunner.query(`DROP INDEX "IDX_0610ebcfcfb4a18441a9bcdab2"`); + await queryRunner.query(`DROP INDEX "IDX_25dfc71b0369b003a4cd434d0b"`); + await queryRunner.query(`DROP INDEX "IDX_2710a55f826ee236ea1a62698f"`); + await queryRunner.query(`DROP INDEX "IDX_4c02d38a976c3ae132228c6fce"`); + await queryRunner.query(`DROP INDEX "IDX_51c063b6a133a9cb87145450f5"`); + await queryRunner.query(`DROP INDEX "IDX_54ebcb6d27222913b908d56fd8"`); + await queryRunner.query(`DROP INDEX "IDX_7fa20a12319c7f6dc3aed98c0a"`); + await queryRunner.query(`DROP INDEX "IDX_88937d94d7443d9a99a76fa5c0"`); + await queryRunner.query(`DROP INDEX "IDX_b11a5e627c41d4dc3170f1d370"`); + await queryRunner.query(`DROP INDEX "IDX_c8dfad3b72196dd1d6b5db168a"`); + await queryRunner.query(`DROP INDEX "IDX_d57f9030cd3af7f63ffb1c267c"`); + await queryRunner.query(`DROP INDEX "IDX_e5848eac4940934e23dbc17581"`); + await queryRunner.query(`DROP INDEX "IDX_fa99d777623947a5b05f394cae"`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE INDEX "IDX_01f4581f114e0ebd2bbb876f0b" ON "note_reaction" ("createdAt")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_0610ebcfcfb4a18441a9bcdab2" ON "poll" ("userId")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_25dfc71b0369b003a4cd434d0b" ON "note" ("attachedFileTypes")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_2710a55f826ee236ea1a62698f" ON "hashtag" ("mentionedUsersCount")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_4c02d38a976c3ae132228c6fce" ON "hashtag" ("mentionedRemoteUsersCount")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_51c063b6a133a9cb87145450f5" ON "note" ("fileIds")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_54ebcb6d27222913b908d56fd8" ON "note" ("mentions")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_7fa20a12319c7f6dc3aed98c0a" ON "poll" ("userHost")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_88937d94d7443d9a99a76fa5c0" ON "note" ("tags")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_b11a5e627c41d4dc3170f1d370" ON "notification" ("createdAt")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_c8dfad3b72196dd1d6b5db168a" ON "drive_file" ("createdAt")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_d57f9030cd3af7f63ffb1c267c" ON "hashtag" ("attachedUsersCount")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_e5848eac4940934e23dbc17581" ON "drive_file" ("uri")`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_fa99d777623947a5b05f394cae" ON "user" ("tags")`, + ); + } +} diff --git a/packages/backend/src/migration/1714888400293-add-user-profile-language.ts b/packages/backend/src/migration/1714888400293-add-user-profile-language.ts new file mode 100644 index 0000000000..8fb6496402 --- /dev/null +++ b/packages/backend/src/migration/1714888400293-add-user-profile-language.ts @@ -0,0 +1,13 @@ +import type { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddUserProfileLanguage1714888400293 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "user_profile" ADD COLUMN "lang" character varying(32)`, + ); + } + + async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "lang"`); + } +} diff --git a/packages/backend/src/misc/download-url.ts b/packages/backend/src/misc/download-url.ts index 0a47395947..08dedcd3ed 100644 --- a/packages/backend/src/misc/download-url.ts +++ b/packages/backend/src/misc/download-url.ts @@ -7,10 +7,10 @@ import chalk from "chalk"; import Logger from "@/services/logger.js"; import IPCIDR from "ip-cidr"; import PrivateIp from "private-ip"; -import { isValidUrl } from "./is-valid-url.js"; +import { isSafeUrl } from "backend-rs"; export async function downloadUrl(url: string, path: string): Promise { - if (!isValidUrl(url)) { + if (!isSafeUrl(url)) { throw new StatusError("Invalid URL", 400); } @@ -43,8 +43,8 @@ export async function downloadUrl(url: string, path: string): Promise { limit: 0, }, }) - .on("redirect", (res: Got.Response, opts: Got.NormalizedOptions) => { - if (!isValidUrl(opts.url)) { + .on("redirect", (_res: Got.Response, opts: Got.NormalizedOptions) => { + if (!isSafeUrl(opts.url)) { downloadLogger.warn(`Invalid URL: ${opts.url}`); req.destroy(); } diff --git a/packages/backend/src/misc/fetch.ts b/packages/backend/src/misc/fetch.ts index 1f8c70a196..5af3b08fa5 100644 --- a/packages/backend/src/misc/fetch.ts +++ b/packages/backend/src/misc/fetch.ts @@ -5,7 +5,7 @@ import CacheableLookup from "cacheable-lookup"; import fetch, { type RequestRedirect } from "node-fetch"; import { HttpProxyAgent, HttpsProxyAgent } from "hpagent"; import { config } from "@/config.js"; -import { isValidUrl } from "./is-valid-url.js"; +import { isSafeUrl } from "backend-rs"; export async function getJson( url: string, @@ -60,7 +60,7 @@ export async function getResponse(args: { size?: number; redirect?: RequestRedirect; }) { - if (!isValidUrl(args.url)) { + if (!isSafeUrl(args.url)) { throw new StatusError("Invalid URL", 400); } @@ -83,7 +83,7 @@ export async function getResponse(args: { }); if (args.redirect === "manual" && [301, 302, 307, 308].includes(res.status)) { - if (!isValidUrl(res.url)) { + if (!isSafeUrl(res.url)) { throw new StatusError("Invalid URL", 400); } return res; diff --git a/packages/backend/src/misc/is-valid-url.ts b/packages/backend/src/misc/is-valid-url.ts deleted file mode 100644 index 5aebefcb71..0000000000 --- a/packages/backend/src/misc/is-valid-url.ts +++ /dev/null @@ -1,20 +0,0 @@ -export function isValidUrl(url: string | URL | undefined): boolean { - if (process.env.NODE_ENV !== "production") return true; - - try { - if (url == null) return false; - - const u = typeof url === "string" ? new URL(url) : url; - if (!u.protocol.match(/^https?:$/) || u.hostname === "unix") { - return false; - } - - if (u.port !== "" && !["80", "443"].includes(u.port)) { - return false; - } - - return true; - } catch { - return false; - } -} diff --git a/packages/backend/src/models/entities/drive-file.ts b/packages/backend/src/models/entities/drive-file.ts index c81d5d7622..e3a7d1c370 100644 --- a/packages/backend/src/models/entities/drive-file.ts +++ b/packages/backend/src/models/entities/drive-file.ts @@ -23,7 +23,6 @@ export class DriveFile { @PrimaryColumn(id()) public id: string; - @Index() @Column("timestamp without time zone", { comment: "The created date of the DriveFile.", }) @@ -147,7 +146,6 @@ export class DriveFile { }) public webpublicAccessKey: string | null; - @Index() @Column("varchar", { length: 512, nullable: true, diff --git a/packages/backend/src/models/entities/hashtag.ts b/packages/backend/src/models/entities/hashtag.ts index 7b3df1cc22..84d817bcd2 100644 --- a/packages/backend/src/models/entities/hashtag.ts +++ b/packages/backend/src/models/entities/hashtag.ts @@ -19,7 +19,6 @@ export class Hashtag { }) public mentionedUserIds: User["id"][]; - @Index() @Column("integer", { default: 0, }) @@ -43,7 +42,6 @@ export class Hashtag { }) public mentionedRemoteUserIds: User["id"][]; - @Index() @Column("integer", { default: 0, }) @@ -55,7 +53,6 @@ export class Hashtag { }) public attachedUserIds: User["id"][]; - @Index() @Column("integer", { default: 0, }) diff --git a/packages/backend/src/models/entities/note-reaction.ts b/packages/backend/src/models/entities/note-reaction.ts index fc57bb6a07..1d2fc567b5 100644 --- a/packages/backend/src/models/entities/note-reaction.ts +++ b/packages/backend/src/models/entities/note-reaction.ts @@ -17,7 +17,6 @@ export class NoteReaction { @PrimaryColumn(id()) public id: string; - @Index() @Column("timestamp without time zone", { comment: "The created date of the NoteReaction.", }) diff --git a/packages/backend/src/models/entities/note.ts b/packages/backend/src/models/entities/note.ts index 94cd8c7b66..3b7315288e 100644 --- a/packages/backend/src/models/entities/note.ts +++ b/packages/backend/src/models/entities/note.ts @@ -139,7 +139,6 @@ export class Note { // FIXME: file id is not removed from this array even if the file is deleted // TODO: drop this column and use note_files - @Index() @Column({ ...id(), array: true, @@ -147,7 +146,6 @@ export class Note { }) public fileIds: DriveFile["id"][]; - @Index() @Column("varchar", { length: 256, array: true, @@ -163,7 +161,6 @@ export class Note { }) public visibleUserIds: User["id"][]; - @Index() @Column({ ...id(), array: true, @@ -184,7 +181,6 @@ export class Note { }) public emojis: string[]; - @Index() @Column("varchar", { length: 128, array: true, diff --git a/packages/backend/src/models/entities/notification.ts b/packages/backend/src/models/entities/notification.ts index 58fc86a72c..57a2a59158 100644 --- a/packages/backend/src/models/entities/notification.ts +++ b/packages/backend/src/models/entities/notification.ts @@ -20,7 +20,6 @@ export class Notification { @PrimaryColumn(id()) public id: string; - @Index() @Column("timestamp without time zone", { comment: "The created date of the Notification.", }) diff --git a/packages/backend/src/models/entities/poll.ts b/packages/backend/src/models/entities/poll.ts index 3cc6df17cf..9ef2091566 100644 --- a/packages/backend/src/models/entities/poll.ts +++ b/packages/backend/src/models/entities/poll.ts @@ -44,14 +44,12 @@ export class Poll { }) public noteVisibility: (typeof noteVisibilities)[number]; - @Index() @Column({ ...id(), comment: "[Denormalized]", }) public userId: User["id"]; - @Index() @Column("varchar", { length: 512, nullable: true, diff --git a/packages/backend/src/models/entities/user-profile.ts b/packages/backend/src/models/entities/user-profile.ts index 2fe2b7a58a..2b9ac79195 100644 --- a/packages/backend/src/models/entities/user-profile.ts +++ b/packages/backend/src/models/entities/user-profile.ts @@ -50,6 +50,12 @@ export class UserProfile { verified?: boolean; }[]; + @Column("varchar", { + length: 32, + nullable: true, + }) + public lang: string | null; + @Column("varchar", { length: 512, nullable: true, diff --git a/packages/backend/src/models/entities/user.ts b/packages/backend/src/models/entities/user.ts index 69a2b4dc27..ad86e72422 100644 --- a/packages/backend/src/models/entities/user.ts +++ b/packages/backend/src/models/entities/user.ts @@ -116,7 +116,6 @@ export class User { }) public bannerId: DriveFile["id"] | null; - @Index() @Column("varchar", { length: 128, array: true, diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts index a5a8771645..0f4ea9f72a 100644 --- a/packages/backend/src/models/repositories/user.ts +++ b/packages/backend/src/models/repositories/user.ts @@ -512,6 +512,7 @@ export const UserRepository = db.getRepository(User).extend({ description: profile!.description, location: profile!.location, birthday: profile!.birthday, + lang: profile!.lang, fields: profile!.fields, followersCount: followersCount ?? null, followingCount: followingCount ?? null, diff --git a/packages/backend/src/models/schema/user.ts b/packages/backend/src/models/schema/user.ts index bcdd718dd1..c7417ce0e4 100644 --- a/packages/backend/src/models/schema/user.ts +++ b/packages/backend/src/models/schema/user.ts @@ -204,6 +204,12 @@ export const packedUserDetailedNotMeOnlySchema = { optional: false, example: "2018-03-12", }, + lang: { + type: "string", + nullable: true, + optional: false, + example: "ja-JP", + }, fields: { type: "array", nullable: false, diff --git a/packages/backend/src/prelude/undefined-to-null.ts b/packages/backend/src/prelude/undefined-to-null.ts index 013be3cf9e..b241f7a653 100644 --- a/packages/backend/src/prelude/undefined-to-null.ts +++ b/packages/backend/src/prelude/undefined-to-null.ts @@ -1,7 +1,7 @@ // https://gist.github.com/tkrotoff/a6baf96eb6b61b445a9142e5555511a0 import type { Primitive } from "type-fest"; -type NullToUndefined = T extends null +export type NullToUndefined = T extends null ? undefined : T extends Primitive | Function | Date | RegExp ? T @@ -15,7 +15,7 @@ type NullToUndefined = T extends null ? { [K in keyof T]: NullToUndefined } : unknown; -type UndefinedToNull = T extends undefined +export type UndefinedToNull = T extends undefined ? null : T extends Primitive | Function | Date | RegExp ? T @@ -47,6 +47,16 @@ function _nullToUndefined(obj: T): NullToUndefined { return obj as any; } +/** + * Recursively converts all null values to undefined. + * + * @param obj object to convert + * @returns a copy of the object with all its null values converted to undefined + */ +export function fromRustObject(obj: T) { + return _nullToUndefined(structuredClone(obj)); +} + function _undefinedToNull(obj: T): UndefinedToNull { if (obj === undefined) { return null as any; @@ -71,6 +81,6 @@ function _undefinedToNull(obj: T): UndefinedToNull { * @param obj object to convert * @returns a copy of the object with all its undefined values converted to null */ -export function undefinedToNull(obj: T) { +export function toRustObject(obj: T) { return _undefinedToNull(structuredClone(obj)); } diff --git a/packages/backend/src/remote/activitypub/misc/contexts.ts b/packages/backend/src/remote/activitypub/misc/contexts.ts index 5b43bf5fc3..d0b3f56fc1 100644 --- a/packages/backend/src/remote/activitypub/misc/contexts.ts +++ b/packages/backend/src/remote/activitypub/misc/contexts.ts @@ -527,7 +527,7 @@ export const WellKnownContext = { manuallyApprovesFollowers: "as:manuallyApprovesFollowers", movedTo: { "@id": "https://www.w3.org/ns/activitystreams#movedTo", - "@type": "@id" + "@type": "@id", }, movedToUri: "as:movedTo", sensitive: "as:sensitive", diff --git a/packages/backend/src/remote/activitypub/request.ts b/packages/backend/src/remote/activitypub/request.ts index 8e3bc764d3..f1f496273d 100644 --- a/packages/backend/src/remote/activitypub/request.ts +++ b/packages/backend/src/remote/activitypub/request.ts @@ -5,8 +5,8 @@ import { StatusError, getResponse } from "@/misc/fetch.js"; import { createSignedPost, createSignedGet } from "./ap-request.js"; import type { Response } from "node-fetch"; import type { IObject } from "./type.js"; -import { isValidUrl } from "@/misc/is-valid-url.js"; import { apLogger } from "@/remote/activitypub/logger.js"; +import { isSafeUrl } from "backend-rs"; export default async (user: { id: User["id"] }, url: string, object: any) => { const body = JSON.stringify(object); @@ -44,7 +44,7 @@ export async function apGet( user?: ILocalUser, redirects: boolean = true, ): Promise<{ finalUrl: string; content: IObject }> { - if (!isValidUrl(url)) { + if (!isSafeUrl(url)) { throw new StatusError("Invalid URL", 400); } diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 734534b3ea..587a68206e 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -286,7 +286,6 @@ import * as ep___pinnedUsers from "./endpoints/pinned-users.js"; import * as ep___customMotd from "./endpoints/custom-motd.js"; import * as ep___customSplashIcons from "./endpoints/custom-splash-icons.js"; import * as ep___latestVersion from "./endpoints/latest-version.js"; -import * as ep___release from "./endpoints/release.js"; import * as ep___promo_read from "./endpoints/promo/read.js"; import * as ep___requestResetPassword from "./endpoints/request-reset-password.js"; import * as ep___resetPassword from "./endpoints/reset-password.js"; @@ -635,7 +634,6 @@ const eps = [ ["custom-motd", ep___customMotd], ["custom-splash-icons", ep___customSplashIcons], ["latest-version", ep___latestVersion], - ["release", ep___release], ["promo/read", ep___promo_read], ["request-reset-password", ep___requestResetPassword], ["reset-password", ep___resetPassword], diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index 9a2b49cb3d..50f0da8f8d 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -87,6 +87,7 @@ export const paramDef = { description: { ...Users.descriptionSchema, nullable: true }, location: { ...Users.locationSchema, nullable: true }, birthday: { ...Users.birthdaySchema, nullable: true }, + lang: { type: "string", nullable: true }, avatarId: { type: "string", format: "misskey:id", nullable: true }, bannerId: { type: "string", format: "misskey:id", nullable: true }, fields: { @@ -154,6 +155,7 @@ export default define(meta, paramDef, async (ps, _user, token) => { if (ps.name !== undefined) updates.name = ps.name; if (ps.description !== undefined) profileUpdates.description = ps.description; + if (typeof ps.lang === "string") profileUpdates.lang = ps.lang; if (ps.location !== undefined) profileUpdates.location = ps.location; if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday; if (ps.ffVisibility !== undefined) diff --git a/packages/backend/src/server/api/endpoints/latest-version.ts b/packages/backend/src/server/api/endpoints/latest-version.ts index 2ca29429b6..e2146303b7 100644 --- a/packages/backend/src/server/api/endpoints/latest-version.ts +++ b/packages/backend/src/server/api/endpoints/latest-version.ts @@ -1,4 +1,5 @@ import define from "@/server/api/define.js"; +import { latestVersion } from "backend-rs"; export const meta = { tags: ["meta"], @@ -14,14 +15,7 @@ export const paramDef = { } as const; export default define(meta, paramDef, async () => { - let latest_version; - await fetch("https://firefish.dev/firefish/firefish/-/raw/main/package.json") - .then((response) => response.json()) - .then((data) => { - latest_version = data.version; - }); - return { - latest_version, + latest_version: await latestVersion(), }; }); diff --git a/packages/backend/src/server/api/endpoints/release.ts b/packages/backend/src/server/api/endpoints/release.ts deleted file mode 100644 index f3a2764295..0000000000 --- a/packages/backend/src/server/api/endpoints/release.ts +++ /dev/null @@ -1,28 +0,0 @@ -import define from "@/server/api/define.js"; - -export const meta = { - tags: ["meta"], - description: "Get release notes from Codeberg", - - requireCredential: false, - requireCredentialPrivateMode: false, -} as const; - -export const paramDef = { - type: "object", - properties: {}, - required: [], -} as const; - -export default define(meta, paramDef, async () => { - let release; - - await fetch( - "https://firefish.dev/firefish/firefish/-/raw/develop/release.json", - ) - .then((response) => response.json()) - .then((data) => { - release = data; - }); - return release; -}); diff --git a/packages/backend/src/server/nodeinfo.ts b/packages/backend/src/server/nodeinfo.ts index 73189b73d9..511d75e254 100644 --- a/packages/backend/src/server/nodeinfo.ts +++ b/packages/backend/src/server/nodeinfo.ts @@ -1,9 +1,7 @@ import Router from "@koa/router"; import { config } from "@/config.js"; -import { fetchMeta } from "backend-rs"; -import { Users, Notes } from "@/models/index.js"; -import { IsNull, MoreThan } from "typeorm"; -import { Cache } from "@/misc/cache.js"; +import { nodeinfo_2_0, nodeinfo_2_1 } from "backend-rs"; +import { fromRustObject } from "@/prelude/undefined-to-null.js"; const router = new Router(); @@ -22,101 +20,14 @@ export const links = [ }, ]; -const nodeinfo2 = async () => { - const now = Date.now(); - const [meta, total, activeHalfyear, activeMonth, localPosts] = - await Promise.all([ - fetchMeta(false), - Users.count({ where: { host: IsNull() } }), - Users.count({ - where: { - host: IsNull(), - lastActiveDate: MoreThan(new Date(now - 15552000000)), - }, - }), - Users.count({ - where: { - host: IsNull(), - lastActiveDate: MoreThan(new Date(now - 2592000000)), - }, - }), - Notes.count({ where: { userHost: IsNull() } }), - ]); - - const proxyAccount = meta.proxyAccountId - ? await Users.pack(meta.proxyAccountId).catch(() => null) - : null; - - return { - software: { - name: "firefish", - version: config.version, - repository: meta.repositoryUrl, - homepage: "https://firefish.dev/firefish/firefish", - }, - protocols: ["activitypub"], - services: { - inbound: [] as string[], - outbound: ["atom1.0", "rss2.0"], - }, - openRegistrations: !meta.disableRegistration, - usage: { - users: { total, activeHalfyear, activeMonth }, - localPosts, - localComments: 0, - }, - metadata: { - nodeName: meta.name, - nodeDescription: meta.description, - maintainer: { - name: meta.maintainerName, - email: meta.maintainerEmail, - }, - langs: meta.langs, - tosUrl: meta.tosUrl, - repositoryUrl: meta.repositoryUrl, - feedbackUrl: meta.feedbackUrl, - disableRegistration: meta.disableRegistration, - disableLocalTimeline: meta.disableLocalTimeline, - disableRecommendedTimeline: meta.disableRecommendedTimeline, - disableGlobalTimeline: meta.disableGlobalTimeline, - emailRequiredForSignup: meta.emailRequiredForSignup, - postEditing: true, - postImports: meta.experimentalFeatures?.postImports || false, - enableHcaptcha: meta.enableHcaptcha, - enableRecaptcha: meta.enableRecaptcha, - maxNoteTextLength: config.maxNoteLength, - maxCaptionTextLength: config.maxCaptionLength, - enableEmail: meta.enableEmail, - enableServiceWorker: meta.enableServiceWorker, - proxyAccountName: proxyAccount ? proxyAccount.username : null, - themeColor: meta.themeColor || "#31748f", - }, - }; -}; - -const cache = new Cache>>( - "nodeinfo", - 60 * 10, -); - router.get(nodeinfo2_1path, async (ctx) => { - const base = await cache.fetch(null, () => nodeinfo2()); - - ctx.body = { version: "2.1", ...base }; - ctx.set("Cache-Control", "public, max-age=600"); + ctx.body = fromRustObject(await nodeinfo_2_1()); + ctx.set("Cache-Control", "public, max-age=3600"); }); router.get(nodeinfo2_0path, async (ctx) => { - const base = await cache.fetch(null, () => nodeinfo2()); - - // @ts-ignore - base.software.repository = undefined; - // @ts-ignore - base.software.homepage = undefined; - - ctx.body = { version: "2.0", ...base }; - ctx.set("Cache-Control", "public, max-age=600"); + ctx.body = fromRustObject(await nodeinfo_2_0()); + ctx.set("Cache-Control", "public, max-age=3600"); }); export default router; diff --git a/packages/backend/src/services/fetch-instance-metadata.ts b/packages/backend/src/services/fetch-instance-metadata.ts index bb9f9d0bd1..d42f93842b 100644 --- a/packages/backend/src/services/fetch-instance-metadata.ts +++ b/packages/backend/src/services/fetch-instance-metadata.ts @@ -10,6 +10,7 @@ import { import { Instances } from "@/models/index.js"; import { getFetchInstanceMetadataLock } from "@/misc/app-lock.js"; import Logger from "@/services/logger.js"; +import { type Nodeinfo, fetchNodeinfo } from "backend-rs"; import { inspect } from "node:util"; const logger = new Logger("metadata", "cyan"); @@ -36,7 +37,7 @@ export async function fetchInstanceMetadata( try { const [info, dom, manifest] = await Promise.all([ - fetchNodeinfo(instance).catch(() => null), + fetchNodeinfo(instance.host).catch(() => null), fetchDom(instance).catch(() => null), fetchManifest(instance).catch(() => null), ]); @@ -57,30 +58,26 @@ export async function fetchInstanceMetadata( if (info) { updates.softwareName = - info.software?.name - ?.toLowerCase() + info.software.name + .toLowerCase() .substring(0, MAX_LENGTH_INSTANCE.softwareName) || null; updates.softwareVersion = - info.software?.version?.substring( + info.software.version.substring( 0, MAX_LENGTH_INSTANCE.softwareVersion, ) || null; updates.openRegistrations = info.openRegistrations; - updates.maintainerName = info.metadata - ? info.metadata.maintainer - ? info.metadata.maintainer.name?.substring( - 0, - MAX_LENGTH_INSTANCE.maintainerName, - ) || null - : null + updates.maintainerName = info.metadata.maintainer + ? info.metadata.maintainer.name?.substring( + 0, + MAX_LENGTH_INSTANCE.maintainerName, + ) || null : null; - updates.maintainerEmail = info.metadata - ? info.metadata.maintainer - ? info.metadata.maintainer.email?.substring( - 0, - MAX_LENGTH_INSTANCE.maintainerEmail, - ) || null - : null + updates.maintainerEmail = info.metadata.maintainer + ? info.metadata.maintainer.email?.substring( + 0, + MAX_LENGTH_INSTANCE.maintainerEmail, + ) || null : null; } @@ -115,75 +112,6 @@ export async function fetchInstanceMetadata( } } -type NodeInfo = { - openRegistrations?: boolean; - software?: { - name?: string; - version?: string; - }; - metadata?: { - name?: string; - nodeName?: string; - nodeDescription?: string; - description?: string; - maintainer?: { - name?: string; - email?: string; - }; - }; -}; - -async function fetchNodeinfo(instance: Instance): Promise { - logger.info(`Fetching nodeinfo of ${instance.host} ...`); - - try { - const wellknown = (await getJson( - `https://${instance.host}/.well-known/nodeinfo`, - ).catch((e) => { - if (e.statusCode === 404) { - throw new Error("No nodeinfo provided"); - } else { - throw new Error(inspect(e)); - } - })) as Record; - - if (wellknown.links == null || !Array.isArray(wellknown.links)) { - throw new Error("No wellknown links"); - } - - const links = wellknown.links as any[]; - - const lnik1_0 = links.find( - (link) => link.rel === "http://nodeinfo.diaspora.software/ns/schema/1.0", - ); - const lnik2_0 = links.find( - (link) => link.rel === "http://nodeinfo.diaspora.software/ns/schema/2.0", - ); - const lnik2_1 = links.find( - (link) => link.rel === "http://nodeinfo.diaspora.software/ns/schema/2.1", - ); - const link = lnik2_1 || lnik2_0 || lnik1_0; - - if (link == null) { - throw new Error("No nodeinfo link provided"); - } - - const info = await getJson(link.href).catch((e) => { - throw new Error(inspect(e)); - }); - - logger.info(`Successfuly fetched nodeinfo of ${instance.host}`); - - return info as NodeInfo; - } catch (e) { - logger.error( - `Failed to fetch nodeinfo of ${instance.host}:\n${inspect(e)}`, - ); - - throw e; - } -} - async function fetchDom(instance: Instance): Promise { logger.info(`Fetching HTML of ${instance.host} ...`); @@ -272,7 +200,7 @@ async function fetchIconUrl( } async function getThemeColor( - info: NodeInfo | null, + info: Nodeinfo | null, doc: Window["document"] | null, manifest: Record | null, ): Promise { @@ -290,7 +218,7 @@ async function getThemeColor( } async function getSiteName( - info: NodeInfo | null, + info: Nodeinfo | null, doc: Window["document"] | null, manifest: Record | null, ): Promise { @@ -318,7 +246,7 @@ async function getSiteName( } async function getDescription( - info: NodeInfo | null, + info: Nodeinfo | null, doc: Window["document"] | null, manifest: Record | null, ): Promise { diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 679a2f886e..2096f8b1a2 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -66,7 +66,7 @@ import { Mutex } from "redis-semaphore"; import { langmap } from "@/misc/langmap.js"; import Logger from "@/services/logger.js"; import { inspect } from "node:util"; -import { undefinedToNull } from "@/prelude/undefined-to-null.js"; +import { toRustObject } from "@/prelude/undefined-to-null.js"; const logger = new Logger("create-note"); @@ -404,7 +404,7 @@ export default async ( checkHitAntenna(antenna, note, user).then((hit) => { if (hit) { // TODO: do this more sanely - addNoteToAntenna(antenna.id, undefinedToNull(note) as Note); + addNoteToAntenna(antenna.id, toRustObject(note)); } }); } diff --git a/packages/client/package.json b/packages/client/package.json index cc679ddfb2..d3bf131cb7 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -21,8 +21,6 @@ "@syuilo/aiscript": "0.17.0", "@types/autosize": "^4.0.3", "@types/glob": "8.1.0", - "@types/gulp": "4.0.17", - "@types/gulp-rename": "2.0.6", "@types/insert-text-at-cursor": "^0.3.2", "@types/katex": "0.16.7", "@types/matter-js": "0.19.6", diff --git a/packages/client/src/account.ts b/packages/client/src/account.ts index cf6fb54915..fb3f70c34e 100644 --- a/packages/client/src/account.ts +++ b/packages/client/src/account.ts @@ -132,6 +132,9 @@ export async function signIn(token: Account["token"], redirect?: string) { if (_DEV_) console.log("logging as token ", token); const newAccount = await fetchAccount(token); localStorage.setItem("account", JSON.stringify(newAccount)); + if (newAccount.lang) { + localStorage.setItem("lang", newAccount.lang); + } document.cookie = `token=${token}; path=/; max-age=31536000`; // bull dashboardの認証とかで使う await addAccount(newAccount.id, token); diff --git a/packages/client/src/components/MkMenu.vue b/packages/client/src/components/MkMenu.vue index a90e42fc29..b874e29d8f 100644 --- a/packages/client/src/components/MkMenu.vue +++ b/packages/client/src/components/MkMenu.vue @@ -130,7 +130,7 @@ v-else-if="item.type === 'parent'" class="_button item parent" :class="{ childShowing: childShowingItem === item }" - @mouseenter="showChildren(item, $event)" + @mouseenter.passive="showChildren(item, $event)" @click.stop="showChildren(item, $event)" > (); diff --git a/packages/client/src/components/MkPullToRefresh.vue b/packages/client/src/components/MkPullToRefresh.vue index e78c597516..76bed9e52f 100644 --- a/packages/client/src/components/MkPullToRefresh.vue +++ b/packages/client/src/components/MkPullToRefresh.vue @@ -44,6 +44,7 @@ const FIRE_THRESHOLD = defaultStore.state.pullToRefreshThreshold; const RELEASE_TRANSITION_DURATION = 200; const PULL_BRAKE_BASE = 1.5; const PULL_BRAKE_FACTOR = 170; +const MAX_PULL_TAN_ANGLE = Math.tan((1 / 6) * Math.PI); // 30° const pullStarted = ref(false); const pullEnded = ref(false); @@ -53,6 +54,7 @@ const pullDistance = ref(0); let disabled = false; const supportPointerDesktop = false; let startScreenY: number | null = null; +let startScreenX: number | null = null; const rootEl = shallowRef(); let scrollEl: HTMLElement | null = null; @@ -72,11 +74,16 @@ function getScreenY(event) { if (supportPointerDesktop) return event.screenY; return event.touches[0].screenY; } +function getScreenX(event) { + if (supportPointerDesktop) return event.screenX; + return event.touches[0].screenX; +} function moveStart(event) { if (!pullStarted.value && !isRefreshing.value && !disabled) { pullStarted.value = true; startScreenY = getScreenY(event); + startScreenX = getScreenX(event); pullDistance.value = 0; } } @@ -117,6 +124,7 @@ async function closeContent() { function moveEnd() { if (pullStarted.value && !isRefreshing.value) { startScreenY = null; + startScreenX = null; if (pullEnded.value) { pullEnded.value = false; isRefreshing.value = true; @@ -146,11 +154,17 @@ function moving(event: TouchEvent | PointerEvent) { moveEnd(); return; } - if (startScreenY === null) { - startScreenY = getScreenY(event); - } + startScreenX ??= getScreenX(event); + startScreenY ??= getScreenY(event); const moveScreenY = getScreenY(event); + const moveScreenX = getScreenX(event); const moveHeight = moveScreenY - startScreenY!; + const moveWidth = moveScreenX - startScreenX!; + if (Math.abs(moveWidth / moveHeight) > MAX_PULL_TAN_ANGLE) { + if (Math.abs(moveWidth) > 30) pullStarted.value = false; + return; + } + pullDistance.value = Math.min(Math.max(moveHeight, 0), MAX_PULL_DISTANCE); if (pullDistance.value > 0) { diff --git a/packages/client/src/components/MkUpdated.vue b/packages/client/src/components/MkUpdated.vue index 7004be11cf..7f519b407a 100644 --- a/packages/client/src/components/MkUpdated.vue +++ b/packages/client/src/components/MkUpdated.vue @@ -10,17 +10,6 @@ {{ i18n.ts.misskeyUpdated }}
✨ {{ version }} 🚀
-
- -
- screenshot -
-
diff --git a/packages/client/src/components/mfm.ts b/packages/client/src/components/mfm.ts index 548e3d51f6..bdba3c0cbe 100644 --- a/packages/client/src/components/mfm.ts +++ b/packages/client/src/components/mfm.ts @@ -283,44 +283,44 @@ export default defineComponent({ ? "perspective(128px) rotateY" : "rotate"; const degrees = Number.parseFloat( - token.props.args.deg.toString() ?? "90", + (token.props.args.deg ?? "90").toString(), ); style = `transform: ${rotate}(${degrees}deg); transform-origin: center center;`; break; } case "position": { const x = Number.parseFloat( - token.props.args.x.toString() ?? "0", + (token.props.args.x ?? "0").toString(), ); const y = Number.parseFloat( - token.props.args.y.toString() ?? "0", + (token.props.args.y ?? "0").toString(), ); style = `transform: translateX(${x}em) translateY(${y}em);`; break; } case "crop": { const top = Number.parseFloat( - token.props.args.top.toString() ?? "0", + (token.props.args.top ?? "0").toString(), ); const right = Number.parseFloat( - token.props.args.right.toString() ?? "0", + (token.props.args.right ?? "0").toString(), ); const bottom = Number.parseFloat( - token.props.args.bottom.toString() ?? "0", + (token.props.args.bottom ?? "0").toString(), ); const left = Number.parseFloat( - token.props.args.left.toString() ?? "0", + (token.props.args.left ?? "0").toString(), ); style = `clip-path: inset(${top}% ${right}% ${bottom}% ${left}%);`; break; } case "scale": { const x = Math.min( - Number.parseFloat(token.props.args.x.toString() ?? "1"), + Number.parseFloat((token.props.args.x ?? "1").toString()), 5, ); const y = Math.min( - Number.parseFloat(token.props.args.y.toString() ?? "1"), + Number.parseFloat((token.props.args.y ?? "1").toString()), 5, ); style = `transform: scale(${x}, ${y});`; diff --git a/packages/client/src/pages/notifications.vue b/packages/client/src/pages/notifications.vue index bc35e298e6..29f452f009 100644 --- a/packages/client/src/pages/notifications.vue +++ b/packages/client/src/pages/notifications.vue @@ -27,6 +27,7 @@ > - + - + @@ -54,6 +57,7 @@ import { computed, ref, watch } from "vue"; import { Virtual } from "swiper/modules"; import { Swiper, SwiperSlide } from "swiper/vue"; +import type { Swiper as SwiperType } from "swiper/types"; import { notificationTypes } from "firefish-js"; import XNotifications from "@/components/MkNotifications.vue"; import XNotes from "@/components/MkNotes.vue"; @@ -70,7 +74,7 @@ const tabs = ["all", "reactions", "mentions", "directNotes"]; const tab = ref(tabs[0]); watch(tab, () => syncSlide(tabs.indexOf(tab.value))); -const includeTypes = ref(null); +const includeTypes = ref<(typeof notificationTypes)[number][] | null>(null); os.api("notifications/mark-all-as-read"); const MOBILE_THRESHOLD = 500; @@ -98,7 +102,7 @@ const directNotesPagination = { function setFilter(ev) { const typeItems = notificationTypes.map((t) => ({ text: i18n.t(`_notification._types.${t}`), - active: includeTypes.value && includeTypes.value.includes(t), + active: includeTypes.value?.includes(t), action: () => { includeTypes.value = [t]; }, @@ -121,25 +125,23 @@ function setFilter(ev) { } const headerActions = computed(() => - [ - tab.value === "all" - ? { + tab.value === "all" + ? [ + { text: i18n.ts.filter, icon: `${icon("ph-funnel")}`, highlighted: includeTypes.value != null, handler: setFilter, - } - : undefined, - tab.value === "all" - ? { + }, + { text: i18n.ts.markAllAsRead, icon: `${icon("ph-check")}`, handler: () => { os.apiWithDialog("notifications/mark-all-as-read"); }, - } - : undefined, - ].filter((x) => x !== undefined), + }, + ] + : [], ); const headerTabs = computed(() => [ @@ -172,18 +174,19 @@ definePageMetadata( })), ); -let swiperRef = null; +let swiperRef: SwiperType | null = null; -function setSwiperRef(swiper) { +function setSwiperRef(swiper: SwiperType) { swiperRef = swiper; syncSlide(tabs.indexOf(tab.value)); } function onSlideChange() { - tab.value = tabs[swiperRef.activeIndex]; + if (tab.value !== tabs[swiperRef!.activeIndex]) + tab.value = tabs[swiperRef!.activeIndex]; } -function syncSlide(index) { - swiperRef.slideTo(index); +function syncSlide(index: number) { + if (index !== swiperRef!.activeIndex) swiperRef!.slideTo(index); } diff --git a/packages/client/src/pages/settings/general.vue b/packages/client/src/pages/settings/general.vue index 05cbe4806a..2ca0e7a534 100644 --- a/packages/client/src/pages/settings/general.vue +++ b/packages/client/src/pages/settings/general.vue @@ -14,6 +14,12 @@ > + + + + @@ -410,6 +416,7 @@ import { deviceKind } from "@/scripts/device-kind"; import icon from "@/scripts/icon"; const lang = ref(localStorage.getItem("lang")); +const serverLang = ref(me?.lang); const translateLang = ref(localStorage.getItem("translateLang")); const fontSize = ref(localStorage.getItem("fontSize")); const useSystemFont = ref(localStorage.getItem("useSystemFont") !== "f"); @@ -571,6 +578,14 @@ const mergeRenotesInTimeline = computed( // }); // } +function updateServerLang() { + os.api("i/update", { + lang: lang.value, + }).then((i) => { + serverLang.value = i.lang; + }); +} + watch(swipeOnDesktop, () => { defaultStore.set("swipeOnMobile", true); }); diff --git a/packages/client/src/scripts/get-user-menu.ts b/packages/client/src/scripts/get-user-menu.ts index 8f286ea8d6..110bbba56b 100644 --- a/packages/client/src/scripts/get-user-menu.ts +++ b/packages/client/src/scripts/get-user-menu.ts @@ -265,14 +265,18 @@ export function getUserMenu(user, router: Router = mainRouter) { icon: "ph-qr-code ph-bold ph-lg", text: i18n.ts.getQrCode, action: () => { - os.displayQrCode(`https://${host}/follow-me?acct=${user.username}`); + os.displayQrCode( + `https://${host}/follow-me?acct=${acct.toString(user)}`, + ); }, }, { icon: `${icon("ph-hand-waving")}`, text: i18n.ts.copyRemoteFollowUrl, action: () => { - copyToClipboard(`https://${host}/follow-me?acct=${user.username}`); + copyToClipboard( + `https://${host}/follow-me?acct=${acct.toString(user)}`, + ); os.success(); }, }, @@ -321,7 +325,7 @@ export function getUserMenu(user, router: Router = mainRouter) { icon: `${icon("ph-hand-waving")}`, text: i18n.ts.remoteFollow, action: () => { - router.push(`/follow-me?acct=${user.username}`); + router.push(`/follow-me?acct=${acct.toString(user)}`); }, } : undefined, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be9bdcb967..f8fa01118d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,18 +8,6 @@ importers: .: dependencies: - gulp: - specifier: 4.0.2 - version: 4.0.2 - gulp-cssnano: - specifier: 2.1.3 - version: 2.1.3 - gulp-replace: - specifier: 1.1.4 - version: 1.1.4 - gulp-terser: - specifier: 2.1.0 - version: 2.1.0 js-yaml: specifier: 4.1.0 version: 4.1.0 @@ -569,12 +557,6 @@ importers: '@types/glob': specifier: 8.1.0 version: 8.1.0 - '@types/gulp': - specifier: 4.0.17 - version: 4.0.17 - '@types/gulp-rename': - specifier: 2.0.6 - version: 2.0.6 '@types/insert-text-at-cursor': specifier: ^0.3.2 version: 0.3.2 @@ -3019,6 +3001,7 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.3.3 '@jridgewell/trace-mapping': 0.3.19 + dev: true /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} @@ -3028,6 +3011,7 @@ packages: dependencies: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 + dev: true /@jridgewell/trace-mapping@0.3.20: resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} @@ -4039,9 +4023,6 @@ packages: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} dev: true - /@types/expect@1.20.4: - resolution: {integrity: sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==} - /@types/express-serve-static-core@4.17.35: resolution: {integrity: sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==} dependencies: @@ -4077,14 +4058,6 @@ packages: '@types/node': 20.12.7 dev: false - /@types/glob-stream@8.0.0: - resolution: {integrity: sha512-fxTWwdQmX9LWSHD7ZLlv3BHR992mKcVcDnT/2v+l/QZZo7TfDdyasqlSYVzOnMGWhRbrWeWkbj/mgezFjKynhw==} - dependencies: - '@types/node': 20.12.7 - '@types/picomatch': 2.3.0 - '@types/streamx': 2.9.1 - dev: true - /@types/glob@8.1.0: resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==} dependencies: @@ -4098,22 +4071,6 @@ packages: '@types/node': 20.12.7 dev: true - /@types/gulp-rename@2.0.6: - resolution: {integrity: sha512-pvZdJ004TpC4Ohk9l0CxEXzS9E0L72b5n6lkIEIaWUIy/RlqnkDMHVtEC6InDjd4rt0jZKcvTrDKxeT96WUYnw==} - dependencies: - '@types/node': 20.12.7 - '@types/vinyl': 2.0.7 - dev: true - - /@types/gulp@4.0.17: - resolution: {integrity: sha512-+pKQynu2C/HS16kgmDlAicjtFYP8kaa86eE9P0Ae7GB5W29we/E2TIdbOWtEZD5XkpY+jr8fyqfwO6SWZecLpQ==} - dependencies: - '@types/node': 20.12.7 - '@types/undertaker': 1.2.8 - '@types/vinyl-fs': 3.0.2 - chokidar: 3.5.3 - dev: true - /@types/http-assert@1.5.3: resolution: {integrity: sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA==} @@ -4352,10 +4309,6 @@ packages: pg-types: 4.0.1 dev: true - /@types/picomatch@2.3.0: - resolution: {integrity: sha512-O397rnSS9iQI4OirieAtsDqvCj4+3eY1J+EPdNTKuHuRWIfUoGyzX294o8C4KJYaLqgSrd2o60c5EqCU8Zv02g==} - dev: true - /@types/prismjs@1.26.3: resolution: {integrity: sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw==} dev: true @@ -4443,12 +4396,6 @@ packages: resolution: {integrity: sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw==} dev: true - /@types/streamx@2.9.1: - resolution: {integrity: sha512-9bywzhouyedmci7WCIPFwJ8zASDnxt2gaVUy52X0p0Tt085IJSAEP0L6j4SSNeDMSLzpYu6cPz0GrJZ7kPJ6Bg==} - dependencies: - '@types/node': 20.12.7 - dev: true - /@types/syslog-pro@1.0.3: resolution: {integrity: sha512-tI558N5Io/04ya5eO5HJRIHLLJK/2Q1y4j6Fb0POVSNgRFxfJCOZHEyNrpcagdEtw9i25Diq3NXfs1qa0yyMIw==} dev: true @@ -4469,18 +4416,6 @@ packages: resolution: {integrity: sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==} dev: true - /@types/undertaker-registry@1.0.1: - resolution: {integrity: sha512-Z4TYuEKn9+RbNVk1Ll2SS4x1JeLHecolIbM/a8gveaHsW0Hr+RQMraZACwTO2VD7JvepgA6UO1A1VrbktQrIbQ==} - dev: true - - /@types/undertaker@1.2.8: - resolution: {integrity: sha512-gW3PRqCHYpo45XFQHJBhch7L6hytPsIe0QeLujlnFsjHPnXLhJcPdN6a9368d7aIQgH2I/dUTPFBlGeSNA3qOg==} - dependencies: - '@types/node': 20.12.7 - '@types/undertaker-registry': 1.0.1 - async-done: 1.3.2 - dev: true - /@types/unist@2.0.7: resolution: {integrity: sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==} dev: true @@ -4493,20 +4428,6 @@ packages: resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} dev: true - /@types/vinyl-fs@3.0.2: - resolution: {integrity: sha512-ctNcmmzbMIKooXjRkyyUCOu2Z4AyqibL+RhXoF3pb7K7j+ezItnakmpm31LymkYHSIM5ey0tjIFzTvFOTSBCGw==} - dependencies: - '@types/glob-stream': 8.0.0 - '@types/node': 20.12.7 - '@types/vinyl': 2.0.7 - dev: true - - /@types/vinyl@2.0.7: - resolution: {integrity: sha512-4UqPv+2567NhMQuMLdKAyK4yzrfCqwaTt6bLhHEs8PFcxbHILsrxaY63n4wgE/BRLDWDQeI+WcTmkXKExh9hQg==} - dependencies: - '@types/expect': 1.20.4 - '@types/node': 20.12.7 - /@types/web-push@3.6.3: resolution: {integrity: sha512-v3oT4mMJsHeJ/rraliZ+7TbZtr5bQQuxcgD7C3/1q/zkAj29c8RE0F9lVZVu3hiQe5Z9fYcBreV7TLnfKR+4mg==} dependencies: @@ -5288,17 +5209,6 @@ packages: uri-js: 4.4.1 dev: false - /alphanum-sort@1.0.2: - resolution: {integrity: sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ==} - dev: false - - /ansi-colors@1.1.0: - resolution: {integrity: sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==} - engines: {node: '>=0.10.0'} - dependencies: - ansi-wrap: 0.1.0 - dev: false - /ansi-colors@4.1.1: resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} engines: {node: '>=6'} @@ -5311,18 +5221,6 @@ packages: type-fest: 0.21.3 dev: true - /ansi-gray@0.1.1: - resolution: {integrity: sha512-HrgGIZUl8h2EHuZaU9hTR/cU5nhKxpVE1V6kdGsQ8e4zirElJ5fvtfc8N7Q1oq1aatO275i8pUFUCpNWCAnVWw==} - engines: {node: '>=0.10.0'} - dependencies: - ansi-wrap: 0.1.0 - dev: false - - /ansi-regex@2.1.1: - resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} - engines: {node: '>=0.10.0'} - dev: false - /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -5336,11 +5234,6 @@ packages: resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==} dev: true - /ansi-styles@2.2.1: - resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} - engines: {node: '>=0.10.0'} - dev: false - /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -5363,24 +5256,10 @@ packages: engines: {node: '>=12'} dev: false - /ansi-wrap@0.1.0: - resolution: {integrity: sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==} - engines: {node: '>=0.10.0'} - dev: false - /any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} dev: false - /anymatch@2.0.0: - resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==} - dependencies: - micromatch: 3.1.10 - normalize-path: 2.1.1 - transitivePeerDependencies: - - supports-color - dev: false - /anymatch@3.1.3: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} @@ -5394,13 +5273,6 @@ packages: engines: {node: '>= 6.0.0'} dev: false - /append-buffer@1.0.2: - resolution: {integrity: sha512-WLbYiXzD3y/ATLZFufV/rZvWdZOs+Z/+5v1rBZ463Jn398pa6kcde27cvozYnBoxXblGZTFfoPpsaEw0orU5BA==} - engines: {node: '>=0.10.0'} - dependencies: - buffer-equal: 1.0.1 - dev: false - /append-field@1.0.0: resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} @@ -5434,10 +5306,6 @@ packages: zip-stream: 6.0.1 dev: false - /archy@1.0.0: - resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} - dev: false - /are-docs-informative@0.0.2: resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} engines: {node: '>=14'} @@ -5450,39 +5318,11 @@ packages: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} dependencies: sprintf-js: 1.0.3 + dev: true /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - /arr-diff@4.0.0: - resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==} - engines: {node: '>=0.10.0'} - dev: false - - /arr-filter@1.1.2: - resolution: {integrity: sha512-A2BETWCqhsecSvCkWAeVBFLH6sXEUGASuzkpjL3GR1SlL/PWL6M3J8EAAld2Uubmh39tvkJTqC9LeLHCUKmFXA==} - engines: {node: '>=0.10.0'} - dependencies: - make-iterator: 1.0.1 - dev: false - - /arr-flatten@1.1.0: - resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} - engines: {node: '>=0.10.0'} - dev: false - - /arr-map@2.0.2: - resolution: {integrity: sha512-tVqVTHt+Q5Xb09qRkbu+DidW1yYzz5izWS2Xm2yFm7qJnmUfz4HPzNxbHkdRJbz2lrqI7S+z17xNYdFcBBO8Hw==} - engines: {node: '>=0.10.0'} - dependencies: - make-iterator: 1.0.1 - dev: false - - /arr-union@3.1.0: - resolution: {integrity: sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==} - engines: {node: '>=0.10.0'} - dev: false - /array-buffer-byte-length@1.0.0: resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} dependencies: @@ -5490,11 +5330,6 @@ packages: is-array-buffer: 3.0.2 dev: true - /array-each@1.0.1: - resolution: {integrity: sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==} - engines: {node: '>=0.10.0'} - dev: false - /array-includes@3.1.6: resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} engines: {node: '>= 0.4'} @@ -5517,45 +5352,11 @@ packages: is-string: 1.0.7 dev: true - /array-initial@1.1.0: - resolution: {integrity: sha512-BC4Yl89vneCYfpLrs5JU2aAu9/a+xWbeKhvISg9PT7eWFB9UlRvI+rKEtk6mgxWr3dSkk9gQ8hCrdqt06NXPdw==} - engines: {node: '>=0.10.0'} - dependencies: - array-slice: 1.1.0 - is-number: 4.0.0 - dev: false - - /array-last@1.3.0: - resolution: {integrity: sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==} - engines: {node: '>=0.10.0'} - dependencies: - is-number: 4.0.0 - dev: false - - /array-slice@1.1.0: - resolution: {integrity: sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==} - engines: {node: '>=0.10.0'} - dev: false - - /array-sort@1.0.0: - resolution: {integrity: sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==} - engines: {node: '>=0.10.0'} - dependencies: - default-compare: 1.0.0 - get-value: 2.0.6 - kind-of: 5.1.0 - dev: false - /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} dev: true - /array-unique@0.3.2: - resolution: {integrity: sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==} - engines: {node: '>=0.10.0'} - dev: false - /array.prototype.findlastindex@1.2.2: resolution: {integrity: sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==} engines: {node: '>= 0.4'} @@ -5661,35 +5462,10 @@ packages: engines: {node: '>=0.8'} dev: false - /assign-symbols@1.0.0: - resolution: {integrity: sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==} - engines: {node: '>=0.10.0'} - dev: false - - /async-done@1.3.2: - resolution: {integrity: sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==} - engines: {node: '>= 0.10'} - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - process-nextick-args: 2.0.1 - stream-exhaust: 1.0.2 - - /async-each@1.0.6: - resolution: {integrity: sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==} - dev: false - /async-lock@1.4.0: resolution: {integrity: sha512-coglx5yIWuetakm3/1dsX9hxCNox22h7+V80RQOu2XUUMidtArxKoZoOtHUPuR84SycKTXzgGzAUR5hJxujyJQ==} dev: false - /async-settle@1.0.0: - resolution: {integrity: sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==} - engines: {node: '>= 0.10'} - dependencies: - async-done: 1.3.2 - dev: false - /async@3.2.4: resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==} dev: false @@ -5705,23 +5481,13 @@ packages: resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} engines: {node: '>= 4.5.0'} hasBin: true + dev: true /autobind-decorator@2.4.0: resolution: {integrity: sha512-OGYhWUO72V6DafbF8PM8rm3EPbfuyMZcJhtm5/n26IDwO18pohE4eNazLoCGhPiXOCD0gEGmrbU3849QvM8bbw==} engines: {node: '>=8.10', npm: '>=6.4.1'} dev: true - /autoprefixer@6.7.7: - resolution: {integrity: sha512-WKExI/eSGgGAkWAO+wMVdFObZV7hQen54UpD1kCCTN3tvlL3W1jL4+lPP/M7MwoP7Q4RHzKtO3JQ4HxYEcd+xQ==} - dependencies: - browserslist: 1.7.7 - caniuse-db: 1.0.30001519 - normalize-range: 0.1.2 - num2fraction: 1.2.2 - postcss: 5.2.18 - postcss-value-parser: 3.3.1 - dev: false - /autosize@6.0.1: resolution: {integrity: sha512-f86EjiUKE6Xvczc4ioP1JBlWG7FKrE13qe/DxBCpe8GCipCq2nFw73aO8QEBKHfSbYGDN5eB9jXWKen7tspDqQ==} dev: true @@ -5865,44 +5631,12 @@ packages: dependencies: '@babel/types': 7.22.10 - /bach@1.2.0: - resolution: {integrity: sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==} - engines: {node: '>= 0.10'} - dependencies: - arr-filter: 1.1.2 - arr-flatten: 1.1.0 - arr-map: 2.0.2 - array-each: 1.0.1 - array-initial: 1.1.0 - array-last: 1.3.0 - async-done: 1.3.2 - async-settle: 1.0.0 - now-and-later: 2.0.1 - dev: false - - /balanced-match@0.4.2: - resolution: {integrity: sha512-STw03mQKnGUYtoNjmowo4F2cRmIIxYEGiMsjjwla/u5P1lxadj/05WkNaFjNiKTgJkj8KiXbgAiRTmcQRwQNtg==} - dev: false - /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - /base@0.11.2: - resolution: {integrity: sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==} - engines: {node: '>=0.10.0'} - dependencies: - cache-base: 1.0.1 - class-utils: 0.3.6 - component-emitter: 1.3.1 - define-property: 1.0.0 - isobject: 3.0.1 - mixin-deep: 1.3.2 - pascalcase: 0.1.1 - dev: false - /bcrypt-pbkdf@1.0.2: resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} dependencies: @@ -5934,29 +5668,11 @@ packages: find-versions: 5.1.0 dev: true - /binary-extensions@1.13.1: - resolution: {integrity: sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==} - engines: {node: '>=0.10.0'} - dev: false - /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} dev: true - /binaryextensions@2.3.0: - resolution: {integrity: sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==} - engines: {node: '>=0.8'} - dev: false - - /bindings@1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - requiresBuild: true - dependencies: - file-uri-to-path: 1.0.0 - dev: false - optional: true - /bl@1.2.3: resolution: {integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==} dependencies: @@ -6002,24 +5718,6 @@ packages: dependencies: balanced-match: 1.0.2 - /braces@2.3.2: - resolution: {integrity: sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==} - engines: {node: '>=0.10.0'} - dependencies: - arr-flatten: 1.1.0 - array-unique: 0.3.2 - extend-shallow: 2.0.1 - fill-range: 4.0.0 - isobject: 3.0.1 - repeat-element: 1.1.4 - snapdragon: 0.8.2 - snapdragon-node: 2.1.1 - split-string: 3.1.0 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: false - /braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} @@ -6046,15 +5744,6 @@ packages: pako: 0.2.9 dev: false - /browserslist@1.7.7: - resolution: {integrity: sha512-qHJblDE2bXVRYzuDetv/wAeHOJyO97+9wxC1cdCtyzgNuSozOyRCiiLaCR1f71AN66lQdVVBipWm63V+a7bPOw==} - deprecated: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools. - hasBin: true - dependencies: - caniuse-db: 1.0.30001519 - electron-to-chromium: 1.4.488 - dev: false - /browserslist@4.22.1: resolution: {integrity: sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -6113,11 +5802,6 @@ packages: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} dev: false - /buffer-equal@1.0.1: - resolution: {integrity: sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==} - engines: {node: '>=0.4'} - dev: false - /buffer-fill@1.0.0: resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==} dev: false @@ -6191,21 +5875,6 @@ packages: engines: {node: '>= 0.8'} dev: false - /cache-base@1.0.1: - resolution: {integrity: sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==} - engines: {node: '>=0.10.0'} - dependencies: - collection-visit: 1.0.0 - component-emitter: 1.3.1 - get-value: 2.0.6 - has-value: 1.0.0 - isobject: 3.0.1 - set-value: 2.0.1 - to-object-path: 0.3.0 - union-value: 1.0.1 - unset-value: 1.0.0 - dev: false - /cache-content-type@1.0.1: resolution: {integrity: sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==} engines: {node: '>= 6.0.0'} @@ -6278,11 +5947,6 @@ packages: quick-lru: 4.0.1 dev: true - /camelcase@3.0.0: - resolution: {integrity: sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==} - engines: {node: '>=0.10.0'} - dev: false - /camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} @@ -6292,19 +5956,6 @@ packages: engines: {node: '>=10'} dev: true - /caniuse-api@1.6.1: - resolution: {integrity: sha512-SBTl70K0PkDUIebbkXrxWqZlHNs0wRgRD6QZ8guctShjbh63gEPfF+Wj0Yw+75f5Y8tSzqAI/NcisYv/cCah2Q==} - dependencies: - browserslist: 1.7.7 - caniuse-db: 1.0.30001519 - lodash.memoize: 4.1.2 - lodash.uniq: 4.5.0 - dev: false - - /caniuse-db@1.0.30001519: - resolution: {integrity: sha512-nY0JTY0Po8r8bNBred32hc3QMr2+I/CsJCGmH6tZaVEFUzLSfv64i1E8VwTqP3Of6yyzu4MDKus2eoR0pHCZ2A==} - dev: false - /caniuse-lite@1.0.30001551: resolution: {integrity: sha512-vtBAez47BoGMMzlbYhfXrMV1kvRF2WP/lqiMuDu1Sb4EE4LKEgjopFDSRtZfdVnslNRpOqV/woE+Xgrwj6VQlg==} @@ -6345,17 +5996,6 @@ packages: chalk: 5.3.0 dev: false - /chalk@1.1.3: - resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} - engines: {node: '>=0.10.0'} - dependencies: - ansi-styles: 2.2.1 - escape-string-regexp: 1.0.5 - has-ansi: 2.0.0 - strip-ansi: 3.0.1 - supports-color: 2.0.0 - dev: false - /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -6461,27 +6101,6 @@ packages: lodash.some: 4.6.0 dev: false - /chokidar@2.1.8: - resolution: {integrity: sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==} - deprecated: Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies - dependencies: - anymatch: 2.0.0 - async-each: 1.0.6 - braces: 2.3.2 - glob-parent: 3.1.0 - inherits: 2.0.4 - is-binary-path: 1.0.1 - is-glob: 4.0.3 - normalize-path: 3.0.0 - path-is-absolute: 1.0.1 - readdirp: 2.2.1 - upath: 1.2.0 - optionalDependencies: - fsevents: 1.2.13 - transitivePeerDependencies: - - supports-color - dev: false - /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -6537,23 +6156,6 @@ packages: resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} dev: true - /clap@1.2.3: - resolution: {integrity: sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==} - engines: {node: '>=0.10.0'} - dependencies: - chalk: 1.1.3 - dev: false - - /class-utils@0.3.6: - resolution: {integrity: sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==} - engines: {node: '>=0.10.0'} - dependencies: - arr-union: 3.1.0 - define-property: 0.2.5 - isobject: 3.0.1 - static-extend: 0.1.2 - dev: false - /clean-regexp@1.0.0: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} @@ -6586,14 +6188,6 @@ packages: engines: {node: '>=6'} dev: true - /cliui@3.2.0: - resolution: {integrity: sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==} - dependencies: - string-width: 1.0.2 - strip-ansi: 3.0.1 - wrap-ansi: 2.1.0 - dev: false - /cliui@6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} dependencies: @@ -6616,36 +6210,15 @@ packages: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - /clone-buffer@1.0.0: - resolution: {integrity: sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==} - engines: {node: '>= 0.10'} - dev: false - /clone-response@1.0.3: resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} dependencies: mimic-response: 1.0.1 - /clone-stats@1.0.0: - resolution: {integrity: sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==} - dev: false - /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} - - /clone@2.1.2: - resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} - engines: {node: '>=0.8'} - dev: false - - /cloneable-readable@1.1.3: - resolution: {integrity: sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==} - dependencies: - inherits: 2.0.4 - process-nextick-args: 2.0.1 - readable-stream: 2.3.8 - dev: false + dev: true /cluster-key-slot@1.1.2: resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} @@ -6674,39 +6247,10 @@ packages: resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - /coa@1.0.4: - resolution: {integrity: sha512-KAGck/eNAmCL0dcT3BiuYwLbExK6lduR8DxM3C1TyDzaXhZHyZ8ooX5I5+na2e3dPFuibfxrGdorr0/Lr7RYCQ==} - engines: {node: '>= 0.8.0'} - dependencies: - q: 1.5.1 - dev: false - - /code-point-at@1.1.0: - resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} - engines: {node: '>=0.10.0'} - dev: false - /collect-v8-coverage@1.0.2: resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} dev: true - /collection-map@1.0.0: - resolution: {integrity: sha512-5D2XXSpkOnleOI21TG7p3T0bGAsZ/XknZpKBmGYyluO8pw4zA3K8ZlrBIbC4FXg3m6z/RNFiUFfT2sQK01+UHA==} - engines: {node: '>=0.10.0'} - dependencies: - arr-map: 2.0.2 - for-own: 1.0.0 - make-iterator: 1.0.1 - dev: false - - /collection-visit@1.0.0: - resolution: {integrity: sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==} - engines: {node: '>=0.10.0'} - dependencies: - map-visit: 1.0.0 - object-visit: 1.0.1 - dev: false - /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -6724,12 +6268,6 @@ packages: /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - /color-string@0.3.0: - resolution: {integrity: sha512-sz29j1bmSDfoAxKIEU6zwoIZXN6BrFbAMIhfYCNyiZXBDuU/aiHlN84lp/xDzL2ubyFhLDobHIlU1X70XRrMDA==} - dependencies: - color-name: 1.1.4 - dev: false - /color-string@1.9.1: resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} dependencies: @@ -6737,19 +6275,6 @@ packages: simple-swizzle: 0.2.2 dev: false - /color-support@1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - dev: false - - /color@0.11.4: - resolution: {integrity: sha512-Ajpjd8asqZ6EdxQeqGzU5WBhhTfJ/0cA4Wlbre7e5vXfmDSmda7Ov6jeKoru+b0vHcb1CqvuroTHp5zIWzhVMA==} - dependencies: - clone: 1.0.4 - color-convert: 1.9.3 - color-string: 0.3.0 - dev: false - /color@4.2.3: resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} engines: {node: '>=12.5.0'} @@ -6762,19 +6287,6 @@ packages: resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} dev: false - /colormin@1.1.2: - resolution: {integrity: sha512-XSEQUUQUR/lXqGyddiNH3XYFUPYlYr1vXy9rTFMsSOw+J7Q6EQkdlQIrTlYn4TccpsOaUE1PYQNjBn20gwCdgQ==} - dependencies: - color: 0.11.4 - css-color-names: 0.0.4 - has: 1.0.3 - dev: false - - /colors@1.1.2: - resolution: {integrity: sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w==} - engines: {node: '>=0.1.90'} - dev: false - /combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -6802,10 +6314,6 @@ packages: resolution: {integrity: sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==} dev: true - /component-emitter@1.3.1: - resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} - dev: false - /compress-commons@6.0.2: resolution: {integrity: sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==} engines: {node: '>= 14'} @@ -7060,18 +6568,6 @@ packages: keygrip: 1.1.0 dev: false - /copy-descriptor@0.1.1: - resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==} - engines: {node: '>=0.10.0'} - dev: false - - /copy-props@2.0.5: - resolution: {integrity: sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==} - dependencies: - each-props: 1.3.2 - is-plain-object: 5.0.0 - dev: false - /copy-to@2.0.1: resolution: {integrity: sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==} dev: false @@ -7189,10 +6685,6 @@ packages: shebang-command: 2.0.0 which: 2.0.2 - /css-color-names@0.0.4: - resolution: {integrity: sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q==} - dev: false - /css-select@1.2.0: resolution: {integrity: sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA==} dependencies: @@ -7220,52 +6712,6 @@ packages: hasBin: true dev: true - /cssnano@3.10.0: - resolution: {integrity: sha512-0o0IMQE0Ezo4b41Yrm8U6Rp9/Ag81vNXY1gZMnT1XhO4DpjEf2utKERqWJbOoz3g1Wdc1d3QSta/cIuJ1wSTEg==} - dependencies: - autoprefixer: 6.7.7 - decamelize: 1.2.0 - defined: 1.0.1 - has: 1.0.3 - object-assign: 4.1.1 - postcss: 5.2.18 - postcss-calc: 5.3.1 - postcss-colormin: 2.2.2 - postcss-convert-values: 2.6.1 - postcss-discard-comments: 2.0.4 - postcss-discard-duplicates: 2.1.0 - postcss-discard-empty: 2.1.0 - postcss-discard-overridden: 0.1.1 - postcss-discard-unused: 2.2.3 - postcss-filter-plugins: 2.0.3 - postcss-merge-idents: 2.1.7 - postcss-merge-longhand: 2.0.2 - postcss-merge-rules: 2.1.2 - postcss-minify-font-values: 1.0.5 - postcss-minify-gradients: 1.0.5 - postcss-minify-params: 1.2.2 - postcss-minify-selectors: 2.1.1 - postcss-normalize-charset: 1.1.1 - postcss-normalize-url: 3.0.8 - postcss-ordered-values: 2.2.3 - postcss-reduce-idents: 2.4.0 - postcss-reduce-initial: 1.0.1 - postcss-reduce-transforms: 1.0.4 - postcss-svgo: 2.1.6 - postcss-unique-selectors: 2.0.2 - postcss-value-parser: 3.3.1 - postcss-zindex: 2.2.0 - dev: false - - /csso@2.3.2: - resolution: {integrity: sha512-FmCI/hmqDeHHLaIQckMhMZneS84yzUZdrWDAvJVVxOwcKE1P1LF9FGmzr1ktIQSxOw6fl3PaQsmfg+GN+VvR3w==} - engines: {node: '>=0.10.0'} - hasBin: true - dependencies: - clap: 1.2.3 - source-map: 0.5.7 - dev: false - /csstype@3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} dev: true @@ -7373,6 +6819,7 @@ packages: /decode-uri-component@0.2.2: resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} engines: {node: '>=0.10'} + dev: true /decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} @@ -7477,18 +6924,6 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - /default-compare@1.0.0: - resolution: {integrity: sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 5.1.0 - dev: false - - /default-resolution@2.0.0: - resolution: {integrity: sha512-2xaP6GiwVwOEbXCGoJ4ufgC76m8cj805jrghScewJC2ZDsb9U0b4BIrba+xt/Uytyd0HvQ6+WymSRTfnYj59GQ==} - engines: {node: '>= 0.10'} - dev: false - /defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} dependencies: @@ -7513,32 +6948,7 @@ packages: dependencies: has-property-descriptors: 1.0.0 object-keys: 1.1.1 - - /define-property@0.2.5: - resolution: {integrity: sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==} - engines: {node: '>=0.10.0'} - dependencies: - is-descriptor: 0.1.7 - dev: false - - /define-property@1.0.0: - resolution: {integrity: sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==} - engines: {node: '>=0.10.0'} - dependencies: - is-descriptor: 1.0.3 - dev: false - - /define-property@2.0.2: - resolution: {integrity: sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==} - engines: {node: '>=0.10.0'} - dependencies: - is-descriptor: 1.0.3 - isobject: 3.0.1 - dev: false - - /defined@1.0.1: - resolution: {integrity: sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==} - dev: false + dev: true /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} @@ -7568,11 +6978,6 @@ packages: engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} dev: false - /detect-file@1.0.0: - resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} - engines: {node: '>=0.10.0'} - dev: false - /detect-libc@2.0.3: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} @@ -7703,13 +7108,6 @@ packages: stream-shift: 1.0.1 dev: false - /each-props@1.3.2: - resolution: {integrity: sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==} - dependencies: - is-plain-object: 2.0.4 - object.defaults: 1.1.0 - dev: false - /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: false @@ -7750,10 +7148,6 @@ packages: jake: 10.8.7 dev: false - /electron-to-chromium@1.4.488: - resolution: {integrity: sha512-Dv4sTjiW7t/UWGL+H8ZkgIjtUAVZDgb/PwGWvMsCT7jipzUV/u5skbLXPFKb6iV0tiddVi/bcS2/kUrczeWgIQ==} - dev: false - /electron-to-chromium@1.4.561: resolution: {integrity: sha512-eS5t4ulWOBfVHdq9SW2dxEaFarj1lPjvJ8PaYMOjY0DecBaj/t4ARziL2IPpDr4atyWwjLFGQ2vo/VCgQFezVQ==} @@ -7822,6 +7216,7 @@ packages: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: is-arrayish: 0.2.1 + dev: true /es-abstract@1.22.1: resolution: {integrity: sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==} @@ -7931,15 +7326,6 @@ packages: ext: 1.7.0 dev: false - /es6-weak-map@2.0.3: - resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} - dependencies: - d: 1.0.1 - es5-ext: 0.10.62 - es6-iterator: 2.0.3 - es6-symbol: 3.1.3 - dev: false - /esbuild@0.20.2: resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} engines: {node: '>=12'} @@ -8824,12 +8210,6 @@ packages: eslint-visitor-keys: 3.4.3 dev: true - /esprima@2.7.3: - resolution: {integrity: sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==} - engines: {node: '>=0.10.0'} - hasBin: true - dev: false - /esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} @@ -8945,28 +8325,6 @@ packages: engines: {node: '>= 0.8.0'} dev: true - /expand-brackets@2.1.4: - resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==} - engines: {node: '>=0.10.0'} - dependencies: - debug: 2.6.9 - define-property: 0.2.5 - extend-shallow: 2.0.1 - posix-character-classes: 0.1.1 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: false - - /expand-tilde@2.0.2: - resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} - engines: {node: '>=0.10.0'} - dependencies: - homedir-polyfill: 1.0.3 - dev: false - /expect@29.7.0: resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -9006,49 +8364,11 @@ packages: is-extendable: 0.1.1 dev: false - /extend-shallow@3.0.2: - resolution: {integrity: sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==} - engines: {node: '>=0.10.0'} - dependencies: - assign-symbols: 1.0.0 - is-extendable: 1.0.1 - dev: false - - /extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: false - - /extglob@2.0.4: - resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==} - engines: {node: '>=0.10.0'} - dependencies: - array-unique: 0.3.2 - define-property: 1.0.0 - expand-brackets: 2.1.4 - extend-shallow: 2.0.1 - fragment-cache: 0.2.1 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: false - /extsprintf@1.3.0: resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} engines: {'0': node >=0.6.0} dev: false - /fancy-log@1.3.3: - resolution: {integrity: sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==} - engines: {node: '>= 0.10'} - dependencies: - ansi-gray: 0.1.1 - color-support: 1.1.3 - parse-node-version: 1.0.1 - time-stamp: 1.1.0 - dev: false - /fast-blurhash@1.1.2: resolution: {integrity: sha512-lJVOgYSlahqkRhrKumNx/SGB2F/qS0D1z7xjGYjb5EZJRtlzySGMniZjkQ9h9Rv8sPmM/V9orEgRiMwazDNH6A==} dev: true @@ -9090,10 +8410,6 @@ packages: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} dev: true - /fast-levenshtein@1.1.4: - resolution: {integrity: sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==} - dev: false - /fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true @@ -9185,12 +8501,6 @@ packages: engines: {node: '>=4'} dev: false - /file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - requiresBuild: true - dev: false - optional: true - /filelist@1.0.4: resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} dependencies: @@ -9211,16 +8521,6 @@ packages: trim-repeated: 2.0.0 dev: true - /fill-range@4.0.0: - resolution: {integrity: sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 2.0.1 - is-number: 3.0.0 - repeat-string: 1.6.1 - to-regex-range: 2.1.1 - dev: false - /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -9228,14 +8528,6 @@ packages: to-regex-range: 5.0.1 dev: true - /find-up@1.1.2: - resolution: {integrity: sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==} - engines: {node: '>=0.10.0'} - dependencies: - path-exists: 2.1.0 - pinkie-promise: 2.0.1 - dev: false - /find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -9258,41 +8550,6 @@ packages: semver-regex: 4.0.5 dev: true - /findup-sync@2.0.0: - resolution: {integrity: sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g==} - engines: {node: '>= 0.10'} - dependencies: - detect-file: 1.0.0 - is-glob: 3.1.0 - micromatch: 3.1.10 - resolve-dir: 1.0.1 - transitivePeerDependencies: - - supports-color - dev: false - - /findup-sync@3.0.0: - resolution: {integrity: sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==} - engines: {node: '>= 0.10'} - dependencies: - detect-file: 1.0.0 - is-glob: 4.0.3 - micromatch: 3.1.10 - resolve-dir: 1.0.1 - transitivePeerDependencies: - - supports-color - dev: false - - /fined@1.2.0: - resolution: {integrity: sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==} - engines: {node: '>= 0.10'} - dependencies: - expand-tilde: 2.0.2 - is-plain-object: 2.0.4 - object.defaults: 1.1.0 - object.pick: 1.3.0 - parse-filepath: 1.0.2 - dev: false - /fix-esm@1.0.1: resolution: {integrity: sha512-EZtb7wPXZS54GaGxaWxMlhd1DUDCnAg5srlYdu/1ZVeW+7wwR3Tp59nu52dXByFs3MBRq+SByx1wDOJpRvLEXw==} dependencies: @@ -9303,11 +8560,6 @@ packages: - supports-color dev: false - /flagged-respawn@1.0.1: - resolution: {integrity: sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==} - engines: {node: '>= 0.10'} - dev: false - /flat-cache@3.0.4: resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -9337,11 +8589,6 @@ packages: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} dev: true - /flatten@1.0.3: - resolution: {integrity: sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==} - deprecated: flatten is deprecated in favor of utility frameworks such as lodash. - dev: false - /fluent-ffmpeg@2.1.2: resolution: {integrity: sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==} engines: {node: '>=0.8.0'} @@ -9350,13 +8597,6 @@ packages: which: 1.3.1 dev: false - /flush-write-stream@1.1.1: - resolution: {integrity: sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==} - dependencies: - inherits: 2.0.4 - readable-stream: 2.3.8 - dev: false - /focus-trap-vue@4.0.3(focus-trap@7.5.4)(vue@3.4.25): resolution: {integrity: sha512-cIX5rybkCAlNZ4IHYJ3nCFIsipDDljJHHjtTO2IgYWkVYg7X9ipUVdab3HzYp88kmHgMwjcB71LYnXRRsF6ZqQ==} peerDependencies: @@ -9408,18 +8648,6 @@ packages: dependencies: is-callable: 1.2.7 - /for-in@1.0.2: - resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} - engines: {node: '>=0.10.0'} - dev: false - - /for-own@1.0.0: - resolution: {integrity: sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==} - engines: {node: '>=0.10.0'} - dependencies: - for-in: 1.0.2 - dev: false - /foreground-child@3.1.1: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} @@ -9466,13 +8694,6 @@ packages: qs: 6.12.1 dev: false - /fragment-cache@0.2.1: - resolution: {integrity: sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==} - engines: {node: '>=0.10.0'} - dependencies: - map-cache: 0.2.2 - dev: false - /fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} @@ -9500,29 +8721,9 @@ packages: universalify: 0.1.2 dev: false - /fs-mkdirp-stream@1.0.0: - resolution: {integrity: sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==} - engines: {node: '>= 0.10'} - dependencies: - graceful-fs: 4.2.11 - through2: 2.0.5 - dev: false - /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - /fsevents@1.2.13: - resolution: {integrity: sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==} - engines: {node: '>= 4.0'} - os: [darwin] - deprecated: The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2 - requiresBuild: true - dependencies: - bindings: 1.5.0 - nan: 2.19.0 - dev: false - optional: true - /fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -9555,10 +8756,6 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - /get-caller-file@1.0.3: - resolution: {integrity: sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==} - dev: false - /get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -9639,24 +8836,12 @@ packages: resolve-pkg-maps: 1.0.0 dev: true - /get-value@2.0.6: - resolution: {integrity: sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==} - engines: {node: '>=0.10.0'} - dev: false - /getpass@0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} dependencies: assert-plus: 1.0.0 dev: false - /glob-parent@3.1.0: - resolution: {integrity: sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==} - dependencies: - is-glob: 3.1.0 - path-dirname: 1.0.2 - dev: false - /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -9671,41 +8856,10 @@ packages: is-glob: 4.0.3 dev: true - /glob-stream@6.1.0: - resolution: {integrity: sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==} - engines: {node: '>= 0.10'} - dependencies: - extend: 3.0.2 - glob: 7.2.3 - glob-parent: 3.1.0 - is-negated-glob: 1.0.0 - ordered-read-streams: 1.0.1 - pumpify: 1.5.1 - readable-stream: 2.3.8 - remove-trailing-separator: 1.1.0 - to-absolute-glob: 2.0.2 - unique-stream: 2.3.1 - dev: false - /glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} dev: true - /glob-watcher@5.0.5: - resolution: {integrity: sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==} - engines: {node: '>= 0.10'} - dependencies: - anymatch: 2.0.0 - async-done: 1.3.2 - chokidar: 2.1.8 - is-negated-glob: 1.0.0 - just-debounce: 1.1.0 - normalize-path: 3.0.0 - object.defaults: 1.1.0 - transitivePeerDependencies: - - supports-color - dev: false - /glob@10.3.10: resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} engines: {node: '>=16 || 14 >=14.17'} @@ -9727,6 +8881,7 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 + dev: true /glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} @@ -9738,26 +8893,6 @@ packages: minimatch: 5.1.6 once: 1.4.0 - /global-modules@1.0.0: - resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==} - engines: {node: '>=0.10.0'} - dependencies: - global-prefix: 1.0.2 - is-windows: 1.0.2 - resolve-dir: 1.0.1 - dev: false - - /global-prefix@1.0.2: - resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==} - engines: {node: '>=0.10.0'} - dependencies: - expand-tilde: 2.0.2 - homedir-polyfill: 1.0.3 - ini: 1.3.8 - is-windows: 1.0.2 - which: 1.3.1 - dev: false - /globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -9800,13 +8935,6 @@ packages: slash: 3.0.0 dev: true - /glogg@1.0.2: - resolution: {integrity: sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==} - engines: {node: '>= 0.10'} - dependencies: - sparkles: 1.0.1 - dev: false - /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -9874,84 +9002,6 @@ packages: resolution: {integrity: sha512-srBfnk4n+Oe/ZnMIOXt3gT605BX9x5+rh/prT2F1SsNJsU1XuMiP0E2aptW481OnonOGACZWBqseH5Z7csHxhQ==} dev: true - /gulp-cli@2.3.0: - resolution: {integrity: sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==} - engines: {node: '>= 0.10'} - hasBin: true - dependencies: - ansi-colors: 1.1.0 - archy: 1.0.0 - array-sort: 1.0.0 - color-support: 1.1.3 - concat-stream: 1.6.2 - copy-props: 2.0.5 - fancy-log: 1.3.3 - gulplog: 1.0.0 - interpret: 1.4.0 - isobject: 3.0.1 - liftoff: 3.1.0 - matchdep: 2.0.0 - mute-stdout: 1.0.1 - pretty-hrtime: 1.0.3 - replace-homedir: 1.0.0 - semver-greatest-satisfied-range: 1.1.0 - v8flags: 3.2.0 - yargs: 7.1.2 - transitivePeerDependencies: - - supports-color - dev: false - - /gulp-cssnano@2.1.3: - resolution: {integrity: sha512-r8qdX5pTXsBb/IRm9loE8Ijz8UiPW/URMC/bKJe4FPNHRaz4aEx8Bev03L0FYHd/7BSGu/ebmfumAkpGuTdenA==} - dependencies: - buffer-from: 1.1.2 - cssnano: 3.10.0 - object-assign: 4.1.1 - plugin-error: 1.0.1 - vinyl-sourcemaps-apply: 0.2.1 - dev: false - - /gulp-replace@1.1.4: - resolution: {integrity: sha512-SVSF7ikuWKhpAW4l4wapAqPPSToJoiNKsbDoUnRrSgwZHH7lH8pbPeQj1aOVYQrbZKhfSVBxVW+Py7vtulRktw==} - engines: {node: '>=10'} - dependencies: - '@types/node': 20.12.7 - '@types/vinyl': 2.0.7 - istextorbinary: 3.3.0 - replacestream: 4.0.3 - yargs-parser: 21.1.1 - dev: false - - /gulp-terser@2.1.0: - resolution: {integrity: sha512-lQ3+JUdHDVISAlUIUSZ/G9Dz/rBQHxOiYDQ70IVWFQeh4b33TC1MCIU+K18w07PS3rq/CVc34aQO4SUbdaNMPQ==} - engines: {node: '>=10'} - dependencies: - plugin-error: 1.0.1 - terser: 5.19.2 - through2: 4.0.2 - vinyl-sourcemaps-apply: 0.2.1 - dev: false - - /gulp@4.0.2: - resolution: {integrity: sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==} - engines: {node: '>= 0.10'} - hasBin: true - dependencies: - glob-watcher: 5.0.5 - gulp-cli: 2.3.0 - undertaker: 1.3.0 - vinyl-fs: 3.0.3 - transitivePeerDependencies: - - supports-color - dev: false - - /gulplog@1.0.0: - resolution: {integrity: sha512-hm6N8nrm3Y08jXie48jsC55eCZz9mnb4OirAStEk2deqeyhXU3C1otDVh+ccttMuc1sBi6RX6ZJ720hs9RCvgw==} - engines: {node: '>= 0.10'} - dependencies: - glogg: 1.0.2 - dev: false - /gunzip-maybe@1.4.2: resolution: {integrity: sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==} hasBin: true @@ -9983,22 +9033,10 @@ packages: engines: {node: '>=6'} dev: true - /has-ansi@2.0.0: - resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} - engines: {node: '>=0.10.0'} - dependencies: - ansi-regex: 2.1.1 - dev: false - /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} dev: true - /has-flag@1.0.0: - resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} - engines: {node: '>=0.10.0'} - dev: false - /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -10011,6 +9049,7 @@ packages: resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} dependencies: get-intrinsic: 1.2.1 + dev: true /has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -10041,37 +9080,6 @@ packages: dependencies: has-symbols: 1.0.3 - /has-value@0.3.1: - resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} - engines: {node: '>=0.10.0'} - dependencies: - get-value: 2.0.6 - has-values: 0.1.4 - isobject: 2.1.0 - dev: false - - /has-value@1.0.0: - resolution: {integrity: sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==} - engines: {node: '>=0.10.0'} - dependencies: - get-value: 2.0.6 - has-values: 1.0.0 - isobject: 3.0.1 - dev: false - - /has-values@0.1.4: - resolution: {integrity: sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==} - engines: {node: '>=0.10.0'} - dev: false - - /has-values@1.0.0: - resolution: {integrity: sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==} - engines: {node: '>=0.10.0'} - dependencies: - is-number: 3.0.0 - kind-of: 4.0.0 - dev: false - /has@1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} @@ -10083,6 +9091,7 @@ packages: engines: {node: '>= 0.4'} dependencies: function-bind: 1.1.2 + dev: true /hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} @@ -10104,15 +9113,9 @@ packages: resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} dev: false - /homedir-polyfill@1.0.3: - resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} - engines: {node: '>=0.10.0'} - dependencies: - parse-passwd: 1.0.0 - dev: false - /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true /hosted-git-info@4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} @@ -10126,10 +9129,6 @@ packages: engines: {node: '>=14'} dev: false - /html-comment-regex@1.1.2: - resolution: {integrity: sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==} - dev: false - /html-entities@2.3.2: resolution: {integrity: sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==} dev: false @@ -10314,10 +9313,6 @@ packages: engines: {node: '>=8'} dev: true - /indexes-of@1.0.1: - resolution: {integrity: sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA==} - dev: false - /inflation@2.0.0: resolution: {integrity: sha512-m3xv4hJYR2oXw4o4Y5l6P5P16WYmazYof+el6Al3f+YlggGj6qT9kImBAnzDelRALnP5d3h4jGBPKzYCizjZZw==} engines: {node: '>= 0.8.0'} @@ -10353,16 +9348,6 @@ packages: side-channel: 1.0.4 dev: true - /interpret@1.4.0: - resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} - engines: {node: '>= 0.10'} - dev: false - - /invert-kv@1.0.0: - resolution: {integrity: sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==} - engines: {node: '>=0.10.0'} - dev: false - /ioredis@5.4.1: resolution: {integrity: sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==} engines: {node: '>=12.22.0'} @@ -10419,26 +9404,6 @@ packages: engines: {node: '>=8'} dev: true - /is-absolute-url@2.1.0: - resolution: {integrity: sha512-vOx7VprsKyllwjSkLV79NIhpyLfr3jAp7VaTCMXOJHu4m0Ew1CZ2fcjASwmV1jI3BWuWHB013M48eyeldk9gYg==} - engines: {node: '>=0.10.0'} - dev: false - - /is-absolute@1.0.0: - resolution: {integrity: sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==} - engines: {node: '>=0.10.0'} - dependencies: - is-relative: 1.0.0 - is-windows: 1.0.2 - dev: false - - /is-accessor-descriptor@1.0.1: - resolution: {integrity: sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==} - engines: {node: '>= 0.10'} - dependencies: - hasown: 2.0.2 - dev: false - /is-alphabetical@1.0.4: resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} dev: true @@ -10468,6 +9433,7 @@ packages: /is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true /is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} @@ -10479,13 +9445,6 @@ packages: has-bigints: 1.0.2 dev: true - /is-binary-path@1.0.1: - resolution: {integrity: sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==} - engines: {node: '>=0.10.0'} - dependencies: - binary-extensions: 1.13.1 - dev: false - /is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -10525,13 +9484,7 @@ packages: resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} dependencies: hasown: 2.0.0 - - /is-data-descriptor@1.0.1: - resolution: {integrity: sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==} - engines: {node: '>= 0.4'} - dependencies: - hasown: 2.0.2 - dev: false + dev: true /is-date-object@1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} @@ -10548,22 +9501,6 @@ packages: resolution: {integrity: sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==} dev: false - /is-descriptor@0.1.7: - resolution: {integrity: sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==} - engines: {node: '>= 0.4'} - dependencies: - is-accessor-descriptor: 1.0.1 - is-data-descriptor: 1.0.1 - dev: false - - /is-descriptor@1.0.3: - resolution: {integrity: sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==} - engines: {node: '>= 0.4'} - dependencies: - is-accessor-descriptor: 1.0.1 - is-data-descriptor: 1.0.1 - dev: false - /is-electron@2.2.2: resolution: {integrity: sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==} dev: false @@ -10579,23 +9516,10 @@ packages: engines: {node: '>=0.10.0'} dev: false - /is-extendable@1.0.1: - resolution: {integrity: sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==} - engines: {node: '>=0.10.0'} - dependencies: - is-plain-object: 2.0.4 - dev: false - /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - - /is-fullwidth-code-point@1.0.0: - resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==} - engines: {node: '>=0.10.0'} - dependencies: - number-is-nan: 1.0.1 - dev: false + dev: true /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} @@ -10613,18 +9537,12 @@ packages: has-tostringtag: 1.0.0 dev: false - /is-glob@3.1.0: - resolution: {integrity: sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: false - /is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 + dev: true /is-gzip@1.0.0: resolution: {integrity: sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==} @@ -10651,11 +9569,6 @@ packages: resolution: {integrity: sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==} dev: false - /is-negated-glob@1.0.0: - resolution: {integrity: sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==} - engines: {node: '>=0.10.0'} - dev: false - /is-negative-zero@2.0.2: resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} engines: {node: '>= 0.4'} @@ -10668,18 +9581,6 @@ packages: has-tostringtag: 1.0.2 dev: true - /is-number@3.0.0: - resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: false - - /is-number@4.0.0: - resolution: {integrity: sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==} - engines: {node: '>=0.10.0'} - dev: false - /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -10693,19 +9594,13 @@ packages: /is-plain-obj@1.1.0: resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} engines: {node: '>=0.10.0'} + dev: true /is-plain-obj@2.1.0: resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} engines: {node: '>=8'} dev: true - /is-plain-object@2.0.4: - resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} - engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - dev: false - /is-plain-object@5.0.0: resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} engines: {node: '>=0.10.0'} @@ -10721,13 +9616,6 @@ packages: call-bind: 1.0.2 has-tostringtag: 1.0.0 - /is-relative@1.0.0: - resolution: {integrity: sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==} - engines: {node: '>=0.10.0'} - dependencies: - is-unc-path: 1.0.0 - dev: false - /is-shared-array-buffer@1.0.2: resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} dependencies: @@ -10754,13 +9642,6 @@ packages: has-tostringtag: 1.0.0 dev: true - /is-svg@2.1.0: - resolution: {integrity: sha512-Ya1giYJUkcL/94quj0+XGcmts6cETPBW1MiFz1ReJrnDJ680F52qpAEGAEGU0nq96FRGIGPx6Yo1CyPXcOoyGw==} - engines: {node: '>=0.10.0'} - dependencies: - html-comment-regex: 1.1.2 - dev: false - /is-svg@5.0.0: resolution: {integrity: sha512-sRl7J0oX9yUNamSdc8cwgzh9KBLnQXNzGmW0RVHwg/jEYjGNYHC6UvnYD8+hAeut9WwxRvhG9biK7g/wDGxcMw==} engines: {node: '>=14.16'} @@ -10793,13 +9674,6 @@ packages: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} dev: false - /is-unc-path@1.0.0: - resolution: {integrity: sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==} - engines: {node: '>=0.10.0'} - dependencies: - unc-path-regex: 0.1.2 - dev: false - /is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} @@ -10809,15 +9683,6 @@ packages: resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} dev: false - /is-utf8@0.2.1: - resolution: {integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==} - dev: false - - /is-valid-glob@1.0.0: - resolution: {integrity: sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==} - engines: {node: '>=0.10.0'} - dev: false - /is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: @@ -10829,11 +9694,6 @@ packages: engines: {node: '>=0.10.0'} dev: false - /is-windows@1.0.2: - resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} - engines: {node: '>=0.10.0'} - dev: false - /isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} @@ -10844,18 +9704,6 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - /isobject@2.1.0: - resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} - engines: {node: '>=0.10.0'} - dependencies: - isarray: 1.0.0 - dev: false - - /isobject@3.0.1: - resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} - engines: {node: '>=0.10.0'} - dev: false - /istanbul-lib-coverage@3.2.0: resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} engines: {node: '>=8'} @@ -10915,14 +9763,6 @@ packages: istanbul-lib-report: 3.0.1 dev: true - /istextorbinary@3.3.0: - resolution: {integrity: sha512-Tvq1W6NAcZeJ8op+Hq7tdZ434rqnMx4CCZ7H0ff83uEloDvVbqAwaMTZcafKGJT0VHkYzuXUiCY4hlXQg6WfoQ==} - engines: {node: '>=8'} - dependencies: - binaryextensions: 2.3.0 - textextensions: 3.3.0 - dev: false - /jackspeak@2.3.6: resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} @@ -11481,10 +10321,6 @@ packages: resolution: {integrity: sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==} dev: false - /js-base64@2.6.4: - resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==} - dev: false - /js-beautify@1.14.9: resolution: {integrity: sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==} engines: {node: '>=12'} @@ -11515,14 +10351,6 @@ packages: esprima: 4.0.1 dev: true - /js-yaml@3.7.0: - resolution: {integrity: sha512-eIlkGty7HGmntbV6P/ZlAsoncFLGsNoM27lkTzS+oneY/EiNhj+geqD9ezg/ip+SW6Var0BJU2JtV0vEUZpWVQ==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 2.7.3 - dev: false - /js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -11584,6 +10412,7 @@ packages: /json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true /json-stringify-safe@5.0.1: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} @@ -11683,10 +10512,6 @@ packages: is-promise: 2.2.2 promise: 7.3.1 - /just-debounce@1.1.0: - resolution: {integrity: sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==} - dev: false - /jwa@2.0.0: resolution: {integrity: sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==} dependencies: @@ -11733,21 +10558,10 @@ packages: is-buffer: 1.1.6 dev: false - /kind-of@4.0.0: - resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} - engines: {node: '>=0.10.0'} - dependencies: - is-buffer: 1.1.6 - dev: false - - /kind-of@5.1.0: - resolution: {integrity: sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==} - engines: {node: '>=0.10.0'} - dev: false - /kind-of@6.0.3: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} + dev: true /kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} @@ -12022,14 +10836,6 @@ packages: engines: {node: '>=14.16'} dev: false - /last-run@1.1.1: - resolution: {integrity: sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==} - engines: {node: '>= 0.10'} - dependencies: - default-resolution: 2.0.0 - es6-weak-map: 2.0.3 - dev: false - /lazystream@1.0.1: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} engines: {node: '>= 0.6.3'} @@ -12037,20 +10843,6 @@ packages: readable-stream: 2.3.8 dev: false - /lcid@1.0.0: - resolution: {integrity: sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==} - engines: {node: '>=0.10.0'} - dependencies: - invert-kv: 1.0.0 - dev: false - - /lead@1.0.0: - resolution: {integrity: sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==} - engines: {node: '>= 0.10'} - dependencies: - flush-write-stream: 1.1.1 - dev: false - /leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -12064,37 +10856,10 @@ packages: type-check: 0.4.0 dev: true - /liftoff@3.1.0: - resolution: {integrity: sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==} - engines: {node: '>= 0.8'} - dependencies: - extend: 3.0.2 - findup-sync: 3.0.0 - fined: 1.2.0 - flagged-respawn: 1.0.1 - is-plain-object: 2.0.4 - object.map: 1.0.1 - rechoir: 0.6.2 - resolve: 1.22.8 - transitivePeerDependencies: - - supports-color - dev: false - /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} dev: true - /load-json-file@1.1.0: - resolution: {integrity: sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==} - engines: {node: '>=0.10.0'} - dependencies: - graceful-fs: 4.2.11 - parse-json: 2.2.0 - pify: 2.3.0 - pinkie-promise: 2.0.1 - strip-bom: 2.0.0 - dev: false - /loader-runner@4.3.0: resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} engines: {node: '>=6.11.5'} @@ -12167,6 +10932,7 @@ packages: /lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + dev: true /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -12191,10 +10957,6 @@ packages: resolution: {integrity: sha512-s8xEQdsp2Tu5zUqVdFSe9C0kR8YlnAJYLqMdkh+pIRBRxF6/apWseLdHl3/+jv2I61dhPwtI/Ff+EqvCpc+N8w==} dev: true - /lodash.uniq@4.5.0: - resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - dev: false - /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -12285,24 +11047,12 @@ packages: /make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - /make-iterator@1.0.1: - resolution: {integrity: sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 6.0.3 - dev: false - /makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} dependencies: tmpl: 1.0.5 dev: true - /map-cache@0.2.2: - resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} - engines: {node: '>=0.10.0'} - dev: false - /map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} engines: {node: '>=0.10.0'} @@ -12313,35 +11063,12 @@ packages: engines: {node: '>=8'} dev: true - /map-visit@1.0.0: - resolution: {integrity: sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==} - engines: {node: '>=0.10.0'} - dependencies: - object-visit: 1.0.1 - dev: false - /marked@4.3.0: resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} engines: {node: '>= 12'} hasBin: true dev: true - /matchdep@2.0.0: - resolution: {integrity: sha512-LFgVbaHIHMqCRuCZyfCtUOq9/Lnzhi7Z0KFUE2fhD54+JN2jLh3hC02RLkqauJ3U4soU6H1J3tfj/Byk7GoEjA==} - engines: {node: '>= 0.10.0'} - dependencies: - findup-sync: 2.0.0 - micromatch: 3.1.10 - resolve: 1.22.8 - stack-trace: 0.0.10 - transitivePeerDependencies: - - supports-color - dev: false - - /math-expression-evaluator@1.4.0: - resolution: {integrity: sha512-4vRUvPyxdO8cWULGTh9dZWL2tZK6LDBvj+OGHBER7poH9Qdt7kXEoj20wiz4lQUbUXQZFjPbe5mVDo9nutizCw==} - dev: false - /matter-js@0.19.0: resolution: {integrity: sha512-v2huwvQGOHTGOkMqtHd2hercCG3f6QAObTisPPHg8TZqq2lz7eIY/5i/5YUV8Ibf3mEioFEmwibcPUF2/fnKKQ==} dev: true @@ -12412,27 +11139,6 @@ packages: - supports-color dev: true - /micromatch@3.1.10: - resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} - engines: {node: '>=0.10.0'} - dependencies: - arr-diff: 4.0.0 - array-unique: 0.3.2 - braces: 2.3.2 - define-property: 2.0.2 - extend-shallow: 3.0.2 - extglob: 2.0.4 - fragment-cache: 0.2.1 - kind-of: 6.0.3 - nanomatch: 1.2.13 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: false - /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} @@ -12545,14 +11251,6 @@ packages: engines: {node: '>=16 || 14 >=14.17'} dev: false - /mixin-deep@1.3.2: - resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} - engines: {node: '>=0.10.0'} - dependencies: - for-in: 1.0.2 - is-extendable: 1.0.1 - dev: false - /mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true @@ -12662,11 +11360,6 @@ packages: type-is: 1.6.18 xtend: 4.0.2 - /mute-stdout@1.0.1: - resolution: {integrity: sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==} - engines: {node: '>= 0.10'} - dev: false - /mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} dependencies: @@ -12675,12 +11368,6 @@ packages: thenify-all: 1.6.0 dev: false - /nan@2.19.0: - resolution: {integrity: sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==} - requiresBuild: true - dev: false - optional: true - /nanoid@3.3.6: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -12692,25 +11379,6 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - /nanomatch@1.2.13: - resolution: {integrity: sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==} - engines: {node: '>=0.10.0'} - dependencies: - arr-diff: 4.0.0 - array-unique: 0.3.2 - define-property: 2.0.2 - extend-shallow: 3.0.2 - fragment-cache: 0.2.1 - is-windows: 1.0.2 - kind-of: 6.0.3 - object.pick: 1.3.0 - regex-not: 1.0.2 - snapdragon: 0.8.2 - to-regex: 3.0.2 - transitivePeerDependencies: - - supports-color - dev: false - /natural-compare-lite@1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} dev: true @@ -12853,6 +11521,7 @@ packages: resolve: 1.22.8 semver: 5.7.2 validate-npm-package-license: 3.0.4 + dev: true /normalize-package-data@3.0.3: resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} @@ -12864,32 +11533,10 @@ packages: validate-npm-package-license: 3.0.4 dev: true - /normalize-path@2.1.1: - resolution: {integrity: sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==} - engines: {node: '>=0.10.0'} - dependencies: - remove-trailing-separator: 1.1.0 - dev: false - /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: false - - /normalize-url@1.9.1: - resolution: {integrity: sha512-A48My/mtCklowHBlI8Fq2jFWK4tX4lJ5E6ytFsSOq1fzpvT0SQSgKhSg7lN5c2uYFOrUAOQp6zhhJnpp1eMloQ==} - engines: {node: '>=4'} - dependencies: - object-assign: 4.1.1 - prepend-http: 1.0.4 - query-string: 4.3.4 - sort-keys: 1.1.2 - dev: false - /normalize-url@6.1.0: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} @@ -12899,13 +11546,6 @@ packages: engines: {node: '>=14.16'} dev: false - /now-and-later@2.0.1: - resolution: {integrity: sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==} - engines: {node: '>= 0.10'} - dependencies: - once: 1.4.0 - dev: false - /npm-run-path@2.0.2: resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} engines: {node: '>=4'} @@ -12939,15 +11579,6 @@ packages: boolbase: 1.0.0 dev: true - /num2fraction@1.2.2: - resolution: {integrity: sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==} - dev: false - - /number-is-nan@1.0.1: - resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==} - engines: {node: '>=0.10.0'} - dev: false - /oauth@0.10.0: resolution: {integrity: sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q==} dev: false @@ -12961,15 +11592,6 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - /object-copy@0.1.0: - resolution: {integrity: sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==} - engines: {node: '>=0.10.0'} - dependencies: - copy-descriptor: 0.1.1 - define-property: 0.2.5 - kind-of: 3.2.2 - dev: false - /object-inspect@1.12.3: resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} dev: true @@ -12981,13 +11603,7 @@ packages: /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - - /object-visit@1.0.1: - resolution: {integrity: sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==} - engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - dev: false + dev: true /object.assign@4.1.4: resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} @@ -12997,16 +11613,7 @@ packages: define-properties: 1.2.0 has-symbols: 1.0.3 object-keys: 1.1.1 - - /object.defaults@1.1.0: - resolution: {integrity: sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==} - engines: {node: '>=0.10.0'} - dependencies: - array-each: 1.0.1 - array-slice: 1.1.0 - for-own: 1.0.0 - isobject: 3.0.1 - dev: false + dev: true /object.fromentries@2.0.6: resolution: {integrity: sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==} @@ -13044,29 +11651,6 @@ packages: get-intrinsic: 1.2.1 dev: true - /object.map@1.0.1: - resolution: {integrity: sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==} - engines: {node: '>=0.10.0'} - dependencies: - for-own: 1.0.0 - make-iterator: 1.0.1 - dev: false - - /object.pick@1.3.0: - resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} - engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - dev: false - - /object.reduce@1.0.1: - resolution: {integrity: sha512-naLhxxpUESbNkRqc35oQ2scZSJueHGQNUfMW/0U37IgN6tE2dgDWg3whf+NEliy3F/QysrO48XKUz/nGPe+AQw==} - engines: {node: '>=0.10.0'} - dependencies: - for-own: 1.0.0 - make-iterator: 1.0.1 - dev: false - /object.values@1.1.6: resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} engines: {node: '>= 0.4'} @@ -13165,12 +11749,6 @@ packages: wcwidth: 1.0.1 dev: true - /ordered-read-streams@1.0.1: - resolution: {integrity: sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==} - dependencies: - readable-stream: 2.3.8 - dev: false - /os-filter-obj@2.0.0: resolution: {integrity: sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg==} engines: {node: '>=4'} @@ -13178,13 +11756,6 @@ packages: arch: 2.2.0 dev: true - /os-locale@1.4.0: - resolution: {integrity: sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==} - engines: {node: '>=0.10.0'} - dependencies: - lcid: 1.0.0 - dev: false - /os-utils@0.0.14: resolution: {integrity: sha512-ajB8csaHLBvJOYsHJkp8YdO2FvlBbf/ZxaYQwXXRDyQ84UoE+uTuLXxqd0shekXMX6Qr/pt/DDyLMRAMsgfWzg==} dev: false @@ -13276,22 +11847,6 @@ packages: is-hexadecimal: 1.0.4 dev: true - /parse-filepath@1.0.2: - resolution: {integrity: sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==} - engines: {node: '>=0.8'} - dependencies: - is-absolute: 1.0.0 - map-cache: 0.2.2 - path-root: 0.1.1 - dev: false - - /parse-json@2.2.0: - resolution: {integrity: sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==} - engines: {node: '>=0.10.0'} - dependencies: - error-ex: 1.3.2 - dev: false - /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -13308,16 +11863,6 @@ packages: xtend: 4.0.2 dev: false - /parse-node-version@1.0.1: - resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} - engines: {node: '>= 0.10'} - dev: false - - /parse-passwd@1.0.0: - resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} - engines: {node: '>=0.10.0'} - dev: false - /parse-srcset@1.0.2: resolution: {integrity: sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==} dev: false @@ -13347,11 +11892,6 @@ packages: engines: {node: '>= 0.8'} dev: false - /pascalcase@0.1.1: - resolution: {integrity: sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==} - engines: {node: '>=0.10.0'} - dev: false - /passthrough-counter@1.0.0: resolution: {integrity: sha512-Wy8PXTLqPAN0oEgBrlnsXPMww3SYJ44tQ8aVrGAI4h4JZYCS0oYqsPqtPR8OhJpv6qFbpbB7XAn0liKV7EXubA==} dev: false @@ -13360,17 +11900,6 @@ packages: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} dev: true - /path-dirname@1.0.2: - resolution: {integrity: sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==} - dev: false - - /path-exists@2.1.0: - resolution: {integrity: sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==} - engines: {node: '>=0.10.0'} - dependencies: - pinkie-promise: 2.0.1 - dev: false - /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -13396,18 +11925,6 @@ packages: /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - /path-root-regex@0.1.2: - resolution: {integrity: sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==} - engines: {node: '>=0.10.0'} - dev: false - - /path-root@0.1.1: - resolution: {integrity: sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==} - engines: {node: '>=0.10.0'} - dependencies: - path-root-regex: 0.1.2 - dev: false - /path-scurry@1.10.1: resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} engines: {node: '>=16 || 14 >=14.17'} @@ -13424,15 +11941,6 @@ packages: resolution: {integrity: sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==} dev: false - /path-type@1.1.0: - resolution: {integrity: sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==} - engines: {node: '>=0.10.0'} - dependencies: - graceful-fs: 4.2.11 - pify: 2.3.0 - pinkie-promise: 2.0.1 - dev: false - /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -13601,16 +12109,6 @@ packages: pathe: 1.1.1 dev: true - /plugin-error@1.0.1: - resolution: {integrity: sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==} - engines: {node: '>= 0.10'} - dependencies: - ansi-colors: 1.1.0 - arr-diff: 4.0.0 - arr-union: 3.1.0 - extend-shallow: 3.0.2 - dev: false - /plur@4.0.0: resolution: {integrity: sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==} engines: {node: '>=10'} @@ -13637,180 +12135,11 @@ packages: hasBin: true dev: true - /posix-character-classes@0.1.1: - resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==} - engines: {node: '>=0.10.0'} - dev: false - /possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} dev: false - /postcss-calc@5.3.1: - resolution: {integrity: sha512-iBcptYFq+QUh9gzP7ta2btw50o40s4uLI4UDVgd5yRAZtUDWc5APdl5yQDd2h/TyiZNbJrv0HiYhT102CMgN7Q==} - dependencies: - postcss: 5.2.18 - postcss-message-helpers: 2.0.0 - reduce-css-calc: 1.3.0 - dev: false - - /postcss-colormin@2.2.2: - resolution: {integrity: sha512-XXitQe+jNNPf+vxvQXIQ1+pvdQKWKgkx8zlJNltcMEmLma1ypDRDQwlLt+6cP26fBreihNhZxohh1rcgCH2W5w==} - dependencies: - colormin: 1.1.2 - postcss: 5.2.18 - postcss-value-parser: 3.3.1 - dev: false - - /postcss-convert-values@2.6.1: - resolution: {integrity: sha512-SE7mf25D3ORUEXpu3WUqQqy0nCbMuM5BEny+ULE/FXdS/0UMA58OdzwvzuHJRpIFlk1uojt16JhaEogtP6W2oA==} - dependencies: - postcss: 5.2.18 - postcss-value-parser: 3.3.1 - dev: false - - /postcss-discard-comments@2.0.4: - resolution: {integrity: sha512-yGbyBDo5FxsImE90LD8C87vgnNlweQkODMkUZlDVM/CBgLr9C5RasLGJxxh9GjVOBeG8NcCMatoqI1pXg8JNXg==} - dependencies: - postcss: 5.2.18 - dev: false - - /postcss-discard-duplicates@2.1.0: - resolution: {integrity: sha512-+lk5W1uqO8qIUTET+UETgj9GWykLC3LOldr7EehmymV0Wu36kyoHimC4cILrAAYpHQ+fr4ypKcWcVNaGzm0reA==} - dependencies: - postcss: 5.2.18 - dev: false - - /postcss-discard-empty@2.1.0: - resolution: {integrity: sha512-IBFoyrwk52dhF+5z/ZAbzq5Jy7Wq0aLUsOn69JNS+7YeuyHaNzJwBIYE0QlUH/p5d3L+OON72Fsexyb7OK/3og==} - dependencies: - postcss: 5.2.18 - dev: false - - /postcss-discard-overridden@0.1.1: - resolution: {integrity: sha512-IyKoDL8QNObOiUc6eBw8kMxBHCfxUaERYTUe2QF8k7j/xiirayDzzkmlR6lMQjrAM1p1DDRTvWrS7Aa8lp6/uA==} - dependencies: - postcss: 5.2.18 - dev: false - - /postcss-discard-unused@2.2.3: - resolution: {integrity: sha512-nCbFNfqYAbKCw9J6PSJubpN9asnrwVLkRDFc4KCwyUEdOtM5XDE/eTW3OpqHrYY1L4fZxgan7LLRAAYYBzwzrg==} - dependencies: - postcss: 5.2.18 - uniqs: 2.0.0 - dev: false - - /postcss-filter-plugins@2.0.3: - resolution: {integrity: sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==} - dependencies: - postcss: 5.2.18 - dev: false - - /postcss-merge-idents@2.1.7: - resolution: {integrity: sha512-9DHmfCZ7/hNHhIKnNkz4CU0ejtGen5BbTRJc13Z2uHfCedeCUsK2WEQoAJRBL+phs68iWK6Qf8Jze71anuysWA==} - dependencies: - has: 1.0.3 - postcss: 5.2.18 - postcss-value-parser: 3.3.1 - dev: false - - /postcss-merge-longhand@2.0.2: - resolution: {integrity: sha512-ma7YvxjdLQdifnc1HFsW/AW6fVfubGyR+X4bE3FOSdBVMY9bZjKVdklHT+odknKBB7FSCfKIHC3yHK7RUAqRPg==} - dependencies: - postcss: 5.2.18 - dev: false - - /postcss-merge-rules@2.1.2: - resolution: {integrity: sha512-Wgg2FS6W3AYBl+5L9poL6ZUISi5YzL+sDCJfM7zNw/Q1qsyVQXXZ2cbVui6mu2cYJpt1hOKCGj1xA4mq/obz/Q==} - dependencies: - browserslist: 1.7.7 - caniuse-api: 1.6.1 - postcss: 5.2.18 - postcss-selector-parser: 2.2.3 - vendors: 1.0.4 - dev: false - - /postcss-message-helpers@2.0.0: - resolution: {integrity: sha512-tPLZzVAiIJp46TBbpXtrUAKqedXSyW5xDEo1sikrfEfnTs+49SBZR/xDdqCiJvSSbtr615xDsaMF3RrxS2jZlA==} - dev: false - - /postcss-minify-font-values@1.0.5: - resolution: {integrity: sha512-vFSPzrJhNe6/8McOLU13XIsERohBJiIFFuC1PolgajOZdRWqRgKITP/A4Z/n4GQhEmtbxmO9NDw3QLaFfE1dFQ==} - dependencies: - object-assign: 4.1.1 - postcss: 5.2.18 - postcss-value-parser: 3.3.1 - dev: false - - /postcss-minify-gradients@1.0.5: - resolution: {integrity: sha512-DZhT0OE+RbVqVyGsTIKx84rU/5cury1jmwPa19bViqYPQu499ZU831yMzzsyC8EhiZVd73+h5Z9xb/DdaBpw7Q==} - dependencies: - postcss: 5.2.18 - postcss-value-parser: 3.3.1 - dev: false - - /postcss-minify-params@1.2.2: - resolution: {integrity: sha512-hhJdMVgP8vasrHbkKAk+ab28vEmPYgyuDzRl31V3BEB3QOR3L5TTIVEWLDNnZZ3+fiTi9d6Ker8GM8S1h8p2Ow==} - dependencies: - alphanum-sort: 1.0.2 - postcss: 5.2.18 - postcss-value-parser: 3.3.1 - uniqs: 2.0.0 - dev: false - - /postcss-minify-selectors@2.1.1: - resolution: {integrity: sha512-e13vxPBSo3ZaPne43KVgM+UETkx3Bs4/Qvm6yXI9HQpQp4nyb7HZ0gKpkF+Wn2x+/dbQ+swNpCdZSbMOT7+TIA==} - dependencies: - alphanum-sort: 1.0.2 - has: 1.0.3 - postcss: 5.2.18 - postcss-selector-parser: 2.2.3 - dev: false - - /postcss-normalize-charset@1.1.1: - resolution: {integrity: sha512-RKgjEks83l8w4yEhztOwNZ+nLSrJ+NvPNhpS+mVDzoaiRHZQVoG7NF2TP5qjwnaN9YswUhj6m1E0S0Z+WDCgEQ==} - dependencies: - postcss: 5.2.18 - dev: false - - /postcss-normalize-url@3.0.8: - resolution: {integrity: sha512-WqtWG6GV2nELsQEFES0RzfL2ebVwmGl/M8VmMbshKto/UClBo+mznX8Zi4/hkThdqx7ijwv+O8HWPdpK7nH/Ig==} - dependencies: - is-absolute-url: 2.1.0 - normalize-url: 1.9.1 - postcss: 5.2.18 - postcss-value-parser: 3.3.1 - dev: false - - /postcss-ordered-values@2.2.3: - resolution: {integrity: sha512-5RB1IUZhkxDCfa5fx/ogp/A82mtq+r7USqS+7zt0e428HJ7+BHCxyeY39ClmkkUtxdOd3mk8gD6d9bjH2BECMg==} - dependencies: - postcss: 5.2.18 - postcss-value-parser: 3.3.1 - dev: false - - /postcss-reduce-idents@2.4.0: - resolution: {integrity: sha512-0+Ow9e8JLtffjumJJFPqvN4qAvokVbdQPnijUDSOX8tfTwrILLP4ETvrZcXZxAtpFLh/U0c+q8oRMJLr1Kiu4w==} - dependencies: - postcss: 5.2.18 - postcss-value-parser: 3.3.1 - dev: false - - /postcss-reduce-initial@1.0.1: - resolution: {integrity: sha512-jJFrV1vWOPCQsIVitawGesRgMgunbclERQ/IRGW7r93uHrVzNQQmHQ7znsOIjJPZ4yWMzs5A8NFhp3AkPHPbDA==} - dependencies: - postcss: 5.2.18 - dev: false - - /postcss-reduce-transforms@1.0.4: - resolution: {integrity: sha512-lGgRqnSuAR5i5uUg1TA33r9UngfTadWxOyL2qx1KuPoCQzfmtaHjp9PuwX7yVyRxG3BWBzeFUaS5uV9eVgnEgQ==} - dependencies: - has: 1.0.3 - postcss: 5.2.18 - postcss-value-parser: 3.3.1 - dev: false - /postcss-safe-parser@6.0.0(postcss@8.4.31): resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} engines: {node: '>=12.0'} @@ -13829,14 +12158,6 @@ packages: postcss: 8.4.31 dev: true - /postcss-selector-parser@2.2.3: - resolution: {integrity: sha512-3pqyakeGhrO0BQ5+/tGTfvi5IAUAhHRayGK8WFSu06aEv2BmHoXw/Mhb+w7VY5HERIuC+QoUI7wgrCcq2hqCVA==} - dependencies: - flatten: 1.0.3 - indexes-of: 1.0.1 - uniq: 1.0.1 - dev: false - /postcss-selector-parser@6.0.13: resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} engines: {node: '>=4'} @@ -13858,45 +12179,6 @@ packages: - supports-color dev: true - /postcss-svgo@2.1.6: - resolution: {integrity: sha512-y5AdQdgBoF4rbpdbeWAJuxE953g/ylRfVNp6mvAi61VCN/Y25Tu9p5mh3CyI42WbTRIiwR9a1GdFtmDnNPeskQ==} - dependencies: - is-svg: 2.1.0 - postcss: 5.2.18 - postcss-value-parser: 3.3.1 - svgo: 0.7.2 - dev: false - - /postcss-unique-selectors@2.0.2: - resolution: {integrity: sha512-WZX8r1M0+IyljoJOJleg3kYm10hxNYF9scqAT7v/xeSX1IdehutOM85SNO0gP9K+bgs86XERr7Ud5u3ch4+D8g==} - dependencies: - alphanum-sort: 1.0.2 - postcss: 5.2.18 - uniqs: 2.0.0 - dev: false - - /postcss-value-parser@3.3.1: - resolution: {integrity: sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==} - dev: false - - /postcss-zindex@2.2.0: - resolution: {integrity: sha512-uhRZ2hRgj0lorxm9cr62B01YzpUe63h0RXMXQ4gWW3oa2rpJh+FJAiEAytaFCPU/VgaBS+uW2SJ1XKyDNz1h4w==} - dependencies: - has: 1.0.3 - postcss: 5.2.18 - uniqs: 2.0.0 - dev: false - - /postcss@5.2.18: - resolution: {integrity: sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==} - engines: {node: '>=0.12'} - dependencies: - chalk: 1.1.3 - js-base64: 2.6.4 - source-map: 0.5.7 - supports-color: 3.2.3 - dev: false - /postcss@8.4.31: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} @@ -13977,11 +12259,6 @@ packages: engines: {node: '>= 0.8.0'} dev: true - /prepend-http@1.0.4: - resolution: {integrity: sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==} - engines: {node: '>=0.10.0'} - dev: false - /prettier-linter-helpers@1.0.0: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} @@ -14004,11 +12281,6 @@ packages: react-is: 18.2.0 dev: true - /pretty-hrtime@1.0.3: - resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==} - engines: {node: '>= 0.8'} - dev: false - /pretty@2.0.0: resolution: {integrity: sha512-G9xUchgTEiNpormdYBl+Pha50gOUovT18IvAe7EYMZ1/f9W/WWMPRn+xI68yXNMUk3QXHDwo/1wV/4NejVNe1w==} engines: {node: '>=0.10.0'} @@ -14219,11 +12491,6 @@ packages: engines: {node: '>=0.6.0', teleport: '>=0.2.0'} dev: false - /q@1.5.1: - resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} - engines: {node: '>=0.6.0', teleport: '>=0.2.0'} - dev: false - /qrcode-generator@1.4.4: resolution: {integrity: sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw==} dev: true @@ -14251,14 +12518,6 @@ packages: side-channel: 1.0.6 dev: false - /query-string@4.3.4: - resolution: {integrity: sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==} - engines: {node: '>=0.10.0'} - dependencies: - object-assign: 4.1.1 - strict-uri-encode: 1.1.0 - dev: false - /querystring@0.2.0: resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==} engines: {node: '>=0.4.x'} @@ -14328,14 +12587,6 @@ packages: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} dev: true - /read-pkg-up@1.0.1: - resolution: {integrity: sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==} - engines: {node: '>=0.10.0'} - dependencies: - find-up: 1.1.2 - read-pkg: 1.1.0 - dev: false - /read-pkg-up@7.0.1: resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} engines: {node: '>=8'} @@ -14345,15 +12596,6 @@ packages: type-fest: 0.8.1 dev: true - /read-pkg@1.1.0: - resolution: {integrity: sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==} - engines: {node: '>=0.10.0'} - dependencies: - load-json-file: 1.1.0 - normalize-package-data: 2.5.0 - path-type: 1.1.0 - dev: false - /read-pkg@5.2.0: resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} engines: {node: '>=8'} @@ -14406,17 +12648,6 @@ packages: minimatch: 5.1.6 dev: false - /readdirp@2.2.1: - resolution: {integrity: sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==} - engines: {node: '>=0.10'} - dependencies: - graceful-fs: 4.2.11 - micromatch: 3.1.10 - readable-stream: 2.3.8 - transitivePeerDependencies: - - supports-color - dev: false - /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -14424,13 +12655,6 @@ packages: picomatch: 2.3.1 dev: true - /rechoir@0.6.2: - resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} - engines: {node: '>= 0.10'} - dependencies: - resolve: 1.22.8 - dev: false - /reconnecting@4.4.1: resolution: {integrity: sha512-2GU8WqGpWVB0FcqJNbTDdRVSTw8W2205r+tWx8EVkFa8Oi5N2pbJeNPm9jHQNjDeQcqVILRNZfUX2RRHu6Zdog==} dev: false @@ -14473,20 +12697,6 @@ packages: - supports-color dev: false - /reduce-css-calc@1.3.0: - resolution: {integrity: sha512-0dVfwYVOlf/LBA2ec4OwQ6p3X9mYxn/wOl2xTcLwjnPYrkgEfPx3VI4eGCH3rQLlPISG5v9I9bkZosKsNRTRKA==} - dependencies: - balanced-match: 0.4.2 - math-expression-evaluator: 1.4.0 - reduce-function-call: 1.0.3 - dev: false - - /reduce-function-call@1.0.3: - resolution: {integrity: sha512-Hl/tuV2VDgWgCSEeWMLwxLZqX7OK59eU1guxXsRKTAyeYimivsKdtcV4fu3r710tpG5GmDKDhQ0HSZLExnNmyQ==} - dependencies: - balanced-match: 1.0.2 - dev: false - /reflect-metadata@0.2.2: resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} dev: false @@ -14499,14 +12709,6 @@ packages: resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} dev: true - /regex-not@1.0.2: - resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 3.0.2 - safe-regex: 1.1.0 - dev: false - /regexp-tree@0.1.27: resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true @@ -14533,27 +12735,6 @@ packages: jsesc: 0.5.0 dev: true - /remove-bom-buffer@3.0.0: - resolution: {integrity: sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==} - engines: {node: '>=0.10.0'} - dependencies: - is-buffer: 1.1.6 - is-utf8: 0.2.1 - dev: false - - /remove-bom-stream@1.2.0: - resolution: {integrity: sha512-wigO8/O08XHb8YPzpDDT+QmRANfW6vLqxfaXm1YXhnFf3AkSLyjfG3GEFg4McZkmgL7KvCj5u2KczkvSP6NfHA==} - engines: {node: '>= 0.10'} - dependencies: - remove-bom-buffer: 3.0.0 - safe-buffer: 5.2.1 - through2: 2.0.5 - dev: false - - /remove-trailing-separator@1.1.0: - resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} - dev: false - /rename@1.0.4: resolution: {integrity: sha512-YMM6Fn3lrFOCjhORKjj+z/yizj8WSzv3F3YUlpJA20fteWCb0HbJU19nvuRBPUM5dWgxJcHP+kix3M+5NowJyA==} dependencies: @@ -14562,38 +12743,6 @@ packages: - supports-color dev: false - /repeat-element@1.1.4: - resolution: {integrity: sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==} - engines: {node: '>=0.10.0'} - dev: false - - /repeat-string@1.6.1: - resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} - engines: {node: '>=0.10'} - dev: false - - /replace-ext@1.0.1: - resolution: {integrity: sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==} - engines: {node: '>= 0.10'} - dev: false - - /replace-homedir@1.0.0: - resolution: {integrity: sha512-CHPV/GAglbIB1tnQgaiysb8H2yCy8WQ7lcEwQ/eT+kLj0QHV8LnJW0zpqpE7RSkrMSRoa+EBoag86clf7WAgSg==} - engines: {node: '>= 0.10'} - dependencies: - homedir-polyfill: 1.0.3 - is-absolute: 1.0.0 - remove-trailing-separator: 1.1.0 - dev: false - - /replacestream@4.0.3: - resolution: {integrity: sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==} - dependencies: - escape-string-regexp: 1.0.5 - object-assign: 4.1.1 - readable-stream: 2.3.8 - dev: false - /require-all@3.0.0: resolution: {integrity: sha512-jPGN876lc5exWYrMcgZSd7U42P0PmVQzxnQB13fCSzmyGnqQWW4WUz5DosZ/qe24hz+5o9lSvW2epBNZ1xa6Fw==} engines: {node: '>= 0.8'} @@ -14608,10 +12757,6 @@ packages: engines: {node: '>=0.10.0'} dev: false - /require-main-filename@1.0.1: - resolution: {integrity: sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==} - dev: false - /require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} @@ -14625,14 +12770,6 @@ packages: resolve-from: 5.0.0 dev: true - /resolve-dir@1.0.1: - resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==} - engines: {node: '>=0.10.0'} - dependencies: - expand-tilde: 2.0.2 - global-modules: 1.0.0 - dev: false - /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -14643,13 +12780,6 @@ packages: engines: {node: '>=8'} dev: true - /resolve-options@1.1.0: - resolution: {integrity: sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==} - engines: {node: '>= 0.10'} - dependencies: - value-or-function: 3.0.0 - dev: false - /resolve-path@1.4.0: resolution: {integrity: sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==} engines: {node: '>= 0.8'} @@ -14662,11 +12792,6 @@ packages: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} dev: true - /resolve-url@0.2.1: - resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==} - deprecated: https://github.com/lydell/resolve-url#deprecated - dev: false - /resolve.exports@2.0.2: resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} engines: {node: '>=10'} @@ -14694,6 +12819,7 @@ packages: is-core-module: 2.13.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + dev: true /responselike@2.0.1: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} @@ -14715,11 +12841,6 @@ packages: signal-exit: 3.0.7 dev: true - /ret@0.1.15: - resolution: {integrity: sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==} - engines: {node: '>=0.12'} - dev: false - /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -14806,12 +12927,6 @@ packages: is-regex: 1.1.4 dev: true - /safe-regex@1.1.0: - resolution: {integrity: sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==} - dependencies: - ret: 0.1.15 - dev: false - /safe-regex@2.1.1: resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==} dependencies: @@ -14873,13 +12988,6 @@ packages: commander: 2.20.3 dev: false - /semver-greatest-satisfied-range@1.1.0: - resolution: {integrity: sha512-Ny/iyOzSSa8M5ML46IAx3iXc6tfOsYU2R4AXi2UpHk60Zrgyq6eqPj/xiOfS0rRl/iiQ/rdJkVjw/5cdUyCntQ==} - engines: {node: '>= 0.10'} - dependencies: - sver-compat: 1.5.0 - dev: false - /semver-regex@4.0.5: resolution: {integrity: sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==} engines: {node: '>=12'} @@ -14895,6 +13003,7 @@ packages: /semver@5.7.2: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true + dev: true /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} @@ -14933,16 +13042,6 @@ packages: gopd: 1.0.1 has-property-descriptors: 1.0.2 - /set-value@2.0.1: - resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 2.0.1 - is-extendable: 0.1.1 - is-plain-object: 2.0.4 - split-string: 3.1.0 - dev: false - /setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} dev: false @@ -15075,38 +13174,6 @@ packages: engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} dev: false - /snapdragon-node@2.1.1: - resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==} - engines: {node: '>=0.10.0'} - dependencies: - define-property: 1.0.0 - isobject: 3.0.1 - snapdragon-util: 3.0.1 - dev: false - - /snapdragon-util@3.0.1: - resolution: {integrity: sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: false - - /snapdragon@0.8.2: - resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==} - engines: {node: '>=0.10.0'} - dependencies: - base: 0.11.2 - debug: 2.6.9 - define-property: 0.2.5 - extend-shallow: 2.0.1 - map-cache: 0.2.2 - source-map: 0.5.7 - source-map-resolve: 0.5.3 - use: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: false - /socks-proxy-agent@7.0.0: resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} engines: {node: '>= 10'} @@ -15138,6 +13205,7 @@ packages: engines: {node: '>=0.10.0'} dependencies: is-plain-obj: 1.1.0 + dev: true /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} @@ -15148,17 +13216,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /source-map-resolve@0.5.3: - resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==} - deprecated: See https://github.com/lydell/source-map-resolve#deprecated - dependencies: - atob: 2.1.2 - decode-uri-component: 0.2.2 - resolve-url: 0.2.1 - source-map-url: 0.4.1 - urix: 0.1.0 - dev: false - /source-map-resolve@0.6.0: resolution: {integrity: sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==} deprecated: See https://github.com/lydell/source-map-resolve#deprecated @@ -15179,45 +13236,35 @@ packages: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - - /source-map-url@0.4.1: - resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} - deprecated: See https://github.com/lydell/source-map-url#deprecated - dev: false - - /source-map@0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} - engines: {node: '>=0.10.0'} - dev: false + dev: true /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + dev: true /source-map@0.7.4: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} dev: true - /sparkles@1.0.1: - resolution: {integrity: sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==} - engines: {node: '>= 0.10'} - dev: false - /spdx-correct@3.2.0: resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} dependencies: spdx-expression-parse: 3.0.1 spdx-license-ids: 3.0.16 + dev: true /spdx-exceptions@2.3.0: resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true /spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} dependencies: spdx-exceptions: 2.3.0 spdx-license-ids: 3.0.16 + dev: true /spdx-expression-parse@4.0.0: resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} @@ -15228,13 +13275,7 @@ packages: /spdx-license-ids@3.0.16: resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} - - /split-string@3.1.0: - resolution: {integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 3.0.2 - dev: false + dev: true /split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} @@ -15243,6 +13284,7 @@ packages: /sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true /sprintf-js@1.1.3: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} @@ -15264,10 +13306,6 @@ packages: tweetnacl: 0.14.5 dev: false - /stack-trace@0.0.10: - resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} - dev: false - /stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -15279,14 +13317,6 @@ packages: resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} dev: false - /static-extend@0.1.2: - resolution: {integrity: sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==} - engines: {node: '>=0.10.0'} - dependencies: - define-property: 0.2.5 - object-copy: 0.1.0 - dev: false - /statuses@1.5.0: resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} engines: {node: '>= 0.6'} @@ -15297,9 +13327,6 @@ packages: engines: {node: '>= 0.8'} dev: false - /stream-exhaust@1.0.2: - resolution: {integrity: sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==} - /stream-parser@0.3.1: resolution: {integrity: sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==} dependencies: @@ -15327,11 +13354,6 @@ packages: resolution: {integrity: sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==} dev: true - /strict-uri-encode@1.1.0: - resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} - engines: {node: '>=0.10.0'} - dev: false - /string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -15340,15 +13362,6 @@ packages: strip-ansi: 6.0.1 dev: true - /string-width@1.0.2: - resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==} - engines: {node: '>=0.10.0'} - dependencies: - code-point-at: 1.1.0 - is-fullwidth-code-point: 1.0.0 - strip-ansi: 3.0.1 - dev: false - /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -15406,13 +13419,6 @@ packages: dependencies: char-regex: 1.0.2 - /strip-ansi@3.0.1: - resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} - engines: {node: '>=0.10.0'} - dependencies: - ansi-regex: 2.1.1 - dev: false - /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -15426,13 +13432,6 @@ packages: ansi-regex: 6.0.1 dev: false - /strip-bom@2.0.0: - resolution: {integrity: sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==} - engines: {node: '>=0.10.0'} - dependencies: - is-utf8: 0.2.1 - dev: false - /strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -15524,18 +13523,6 @@ packages: - supports-color dev: false - /supports-color@2.0.0: - resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} - engines: {node: '>=0.8.0'} - dev: false - - /supports-color@3.2.3: - resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} - engines: {node: '>=0.8.0'} - dependencies: - has-flag: 1.0.0 - dev: false - /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -15566,28 +13553,6 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - /sver-compat@1.5.0: - resolution: {integrity: sha512-aFTHfmjwizMNlNE6dsGmoAM4lHjL0CyiobWaFiXWSlD7cIxshW422Nb8KbXCmR6z+0ZEPY+daXJrDyh/vuwTyg==} - dependencies: - es6-iterator: 2.0.3 - es6-symbol: 3.1.3 - dev: false - - /svgo@0.7.2: - resolution: {integrity: sha512-jT/g9FFMoe9lu2IT6HtAxTA7RR2XOrmcrmCtGnyB/+GQnV6ZjNn+KOHZbZ35yL81+1F/aB6OeEsJztzBQ2EEwA==} - engines: {node: '>=0.10.0'} - deprecated: This SVGO version is no longer supported. Upgrade to v2.x.x. - hasBin: true - dependencies: - coa: 1.0.4 - colors: 1.1.2 - csso: 2.3.2 - js-yaml: 3.7.0 - mkdirp: 0.5.6 - sax: 1.2.4 - whet.extend: 0.9.9 - dev: false - /swc-loader@0.2.6(@swc/core@1.5.0)(webpack@5.91.0): resolution: {integrity: sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==} peerDependencies: @@ -15692,17 +13657,6 @@ packages: webpack: 5.91.0(@swc/core@1.5.0) dev: true - /terser@5.19.2: - resolution: {integrity: sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - '@jridgewell/source-map': 0.3.5 - acorn: 8.10.0 - commander: 2.20.3 - source-map-support: 0.5.21 - dev: false - /terser@5.27.0: resolution: {integrity: sha512-bi1HRwVRskAjheeYl291n3JC4GgO/Ty4z1nVs5AAsmonJulGxpSektecnNedrwK9C7vpvVtcX3cw00VSLt7U2A==} engines: {node: '>=10'} @@ -15753,11 +13707,6 @@ packages: resolution: {integrity: sha512-cXAvzO9pP5CGa6NKx0WYHl+8CHKZs8byMkt3PCJBCmq2a34YA9pO1NrQET5pzeqnBjBdToF5No4rrmkDUgQC2Q==} dev: true - /textextensions@3.3.0: - resolution: {integrity: sha512-mk82dS8eRABNbeVJrEiN5/UMSCliINAuz8mkUwH4SwslkNP//gbEzlWNS5au0z5Dpx40SQxzqZevZkn+WYJ9Dw==} - engines: {node: '>=8'} - dev: false - /thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -15780,13 +13729,6 @@ packages: engines: {node: '>=12.22'} dev: true - /through2-filter@3.0.0: - resolution: {integrity: sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==} - dependencies: - through2: 2.0.5 - xtend: 4.0.2 - dev: false - /through2@2.0.5: resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} dependencies: @@ -15794,21 +13736,10 @@ packages: xtend: 4.0.2 dev: false - /through2@4.0.2: - resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} - dependencies: - readable-stream: 3.6.2 - dev: false - /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: false - /time-stamp@1.1.0: - resolution: {integrity: sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw==} - engines: {node: '>=0.10.0'} - dev: false - /tinycolor2@1.6.0: resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} @@ -15827,14 +13758,6 @@ packages: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} dev: true - /to-absolute-glob@2.0.2: - resolution: {integrity: sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==} - engines: {node: '>=0.10.0'} - dependencies: - is-absolute: 1.0.0 - is-negated-glob: 1.0.0 - dev: false - /to-buffer@1.1.1: resolution: {integrity: sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==} dev: false @@ -15843,21 +13766,6 @@ packages: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} - /to-object-path@0.3.0: - resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} - engines: {node: '>=0.10.0'} - dependencies: - kind-of: 3.2.2 - dev: false - - /to-regex-range@2.1.1: - resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} - engines: {node: '>=0.10.0'} - dependencies: - is-number: 3.0.0 - repeat-string: 1.6.1 - dev: false - /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -15865,23 +13773,6 @@ packages: is-number: 7.0.0 dev: true - /to-regex@3.0.2: - resolution: {integrity: sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==} - engines: {node: '>=0.10.0'} - dependencies: - define-property: 2.0.2 - extend-shallow: 3.0.2 - regex-not: 1.0.2 - safe-regex: 1.1.0 - dev: false - - /to-through@2.0.0: - resolution: {integrity: sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==} - engines: {node: '>= 0.10'} - dependencies: - through2: 2.0.5 - dev: false - /toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} @@ -16354,32 +14245,6 @@ packages: through: 2.3.8 dev: false - /unc-path-regex@0.1.2: - resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} - engines: {node: '>=0.10.0'} - dev: false - - /undertaker-registry@1.0.1: - resolution: {integrity: sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==} - engines: {node: '>= 0.10'} - dev: false - - /undertaker@1.3.0: - resolution: {integrity: sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==} - engines: {node: '>= 0.10'} - dependencies: - arr-flatten: 1.1.0 - arr-map: 2.0.2 - bach: 1.2.0 - collection-map: 1.0.0 - es6-weak-map: 2.0.3 - fast-levenshtein: 1.1.4 - last-run: 1.1.1 - object.defaults: 1.1.0 - object.reduce: 1.0.1 - undertaker-registry: 1.0.1 - dev: false - /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -16394,31 +14259,6 @@ packages: resolution: {integrity: sha512-tAYF+EsOxa8jo/XPNYHRX7Nc8uoII+/edIpHM4DQI4nMp3AuRmwGZhL8fEBe0kUk0zHK+6wiwxxxNwfW5ap2Tg==} dev: true - /union-value@1.0.1: - resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} - engines: {node: '>=0.10.0'} - dependencies: - arr-union: 3.1.0 - get-value: 2.0.6 - is-extendable: 0.1.1 - set-value: 2.0.1 - dev: false - - /uniq@1.0.1: - resolution: {integrity: sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==} - dev: false - - /uniqs@2.0.0: - resolution: {integrity: sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ==} - dev: false - - /unique-stream@2.3.1: - resolution: {integrity: sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==} - dependencies: - json-stable-stringify-without-jsonify: 1.0.1 - through2-filter: 3.0.0 - dev: false - /unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} dependencies: @@ -16444,19 +14284,6 @@ packages: engines: {node: '>= 0.8'} dev: false - /unset-value@1.0.0: - resolution: {integrity: sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==} - engines: {node: '>=0.10.0'} - dependencies: - has-value: 0.3.1 - isobject: 3.0.1 - dev: false - - /upath@1.2.0: - resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} - engines: {node: '>=4'} - dev: false - /update-browserslist-db@1.0.13(browserslist@4.22.1): resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} hasBin: true @@ -16483,11 +14310,6 @@ packages: dependencies: punycode: 2.3.1 - /urix@0.1.0: - resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==} - deprecated: Please see https://github.com/lydell/urix#deprecated - dev: false - /url-polyfill@1.1.12: resolution: {integrity: sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A==} dev: true @@ -16499,11 +14321,6 @@ packages: querystring: 0.2.0 dev: false - /use@3.1.1: - resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} - engines: {node: '>=0.10.0'} - dev: false - /utf-8-validate@5.0.10: resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==} engines: {node: '>=6.14.2'} @@ -16556,33 +14373,18 @@ packages: convert-source-map: 2.0.0 dev: true - /v8flags@3.2.0: - resolution: {integrity: sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==} - engines: {node: '>= 0.10'} - dependencies: - homedir-polyfill: 1.0.3 - dev: false - /validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} dependencies: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - - /value-or-function@3.0.0: - resolution: {integrity: sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==} - engines: {node: '>= 0.10'} - dev: false + dev: true /vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} dev: false - /vendors@1.0.4: - resolution: {integrity: sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==} - dev: false - /verror@1.10.0: resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} engines: {'0': node >=0.6.0} @@ -16592,60 +14394,6 @@ packages: extsprintf: 1.3.0 dev: false - /vinyl-fs@3.0.3: - resolution: {integrity: sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==} - engines: {node: '>= 0.10'} - dependencies: - fs-mkdirp-stream: 1.0.0 - glob-stream: 6.1.0 - graceful-fs: 4.2.11 - is-valid-glob: 1.0.0 - lazystream: 1.0.1 - lead: 1.0.0 - object.assign: 4.1.4 - pumpify: 1.5.1 - readable-stream: 2.3.8 - remove-bom-buffer: 3.0.0 - remove-bom-stream: 1.2.0 - resolve-options: 1.1.0 - through2: 2.0.5 - to-through: 2.0.0 - value-or-function: 3.0.0 - vinyl: 2.2.1 - vinyl-sourcemap: 1.1.0 - dev: false - - /vinyl-sourcemap@1.1.0: - resolution: {integrity: sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==} - engines: {node: '>= 0.10'} - dependencies: - append-buffer: 1.0.2 - convert-source-map: 1.9.0 - graceful-fs: 4.2.11 - normalize-path: 2.1.1 - now-and-later: 2.0.1 - remove-bom-buffer: 3.0.0 - vinyl: 2.2.1 - dev: false - - /vinyl-sourcemaps-apply@0.2.1: - resolution: {integrity: sha512-+oDh3KYZBoZC8hfocrbrxbLUeaYtQK7J5WU5Br9VqWqmCll3tFJqKp97GC9GmMsVIL0qnx2DgEDVxdo5EZ5sSw==} - dependencies: - source-map: 0.5.7 - dev: false - - /vinyl@2.2.1: - resolution: {integrity: sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==} - engines: {node: '>= 0.10'} - dependencies: - clone: 2.1.2 - clone-buffer: 1.0.0 - clone-stats: 1.0.0 - cloneable-readable: 1.1.3 - remove-trailing-separator: 1.1.0 - replace-ext: 1.0.1 - dev: false - /vite-plugin-compression@0.5.1(vite@5.2.10): resolution: {integrity: sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==} peerDependencies: @@ -16954,11 +14702,6 @@ packages: tr46: 0.0.3 webidl-conversions: 3.0.1 - /whet.extend@0.9.9: - resolution: {integrity: sha512-mmIPAft2vTgEILgPeZFqE/wWh24SEsR/k+N9fJ3Jxrz44iDFy9aemCxdksfURSHYFCLmvs/d/7Iso5XjPpNfrA==} - engines: {node: '>=0.6.0'} - dev: false - /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: @@ -16969,10 +14712,6 @@ packages: is-symbol: 1.0.4 dev: true - /which-module@1.0.0: - resolution: {integrity: sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==} - dev: false - /which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} @@ -17024,14 +14763,6 @@ packages: resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} dev: true - /wrap-ansi@2.1.0: - resolution: {integrity: sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==} - engines: {node: '>=0.10.0'} - dependencies: - string-width: 1.0.2 - strip-ansi: 3.0.1 - dev: false - /wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -17135,10 +14866,6 @@ packages: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} - /y18n@3.2.2: - resolution: {integrity: sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==} - dev: false - /y18n@4.0.3: resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} @@ -17199,13 +14926,6 @@ packages: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - /yargs-parser@5.0.1: - resolution: {integrity: sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==} - dependencies: - camelcase: 3.0.0 - object.assign: 4.1.4 - dev: false - /yargs-unparser@2.0.0: resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} engines: {node: '>=10'} @@ -17256,24 +14976,6 @@ packages: y18n: 5.0.8 yargs-parser: 21.1.1 - /yargs@7.1.2: - resolution: {integrity: sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==} - dependencies: - camelcase: 3.0.0 - cliui: 3.2.0 - decamelize: 1.2.0 - get-caller-file: 1.0.3 - os-locale: 1.4.0 - read-pkg-up: 1.0.1 - require-directory: 2.1.1 - require-main-filename: 1.0.1 - set-blocking: 2.0.0 - string-width: 1.0.2 - which-module: 1.0.0 - y18n: 3.2.2 - yargs-parser: 5.0.1 - dev: false - /yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} dependencies: diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000000..d6f15c4854 --- /dev/null +++ b/renovate.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["config:base"], + "rangeStrategy": "bump", + "branchConcurrentLimit": 5, + "enabledManagers": ["npm", "cargo"], + "baseBranches": ["develop"], + "lockFileMaintenance": { + "enabled": true, + "recreateWhen": "always", + "rebaseStalePrs": true, + "branchTopic": "lock-file-maintenance", + "commitMessageAction": "Lock file maintenance" + } +} diff --git a/scripts/copy-assets.mjs b/scripts/copy-assets.mjs new file mode 100644 index 0000000000..c5bb35272c --- /dev/null +++ b/scripts/copy-assets.mjs @@ -0,0 +1,41 @@ +import fs from "node:fs/promises"; +import path, { join } from "node:path"; +import { fileURLToPath } from "node:url"; + +const repositoryRootDir = join(path.dirname(fileURLToPath(import.meta.url)), "../"); +const file = (relativePath) => join(repositoryRootDir, relativePath); + +await (async () => { + await fs.rm(file("built/_client_dist_/locales"), { recursive: true, force: true }); + await Promise.all([ + fs.cp(file("packages/backend/src/server/web"), file("packages/backend/built/server/web"), { recursive: true }), + fs.cp(file("custom/assets"), file("packages/backend/assets"), { recursive: true }), + fs.cp(file("packages/client/node_modules/three/examples/fonts"), file("built/_client_dist_/fonts"), { recursive: true }), + fs.mkdir(file("built/_client_dist_/locales"), { recursive: true }), + ]); + + const locales = (await import("../locales/index.mjs")).default; + const meta = (await import("../built/meta.json", { assert: { type: "json" } })).default; + + for await (const [lang, locale] of Object.entries(locales)) { + await fs.writeFile( + file(`built/_client_dist_/locales/${lang}.${meta.version}.json`), + JSON.stringify({ ...locale, _version_: meta.version }), + "utf-8", + ); + } + + const js_assets = [ + file("packages/backend/built/server/web/boot.js"), + file("packages/backend/built/server/web/bios.js"), + file("packages/backend/built/server/web/cli.js"), + ]; + + for await (const js_file of js_assets) { + const content = (await fs.readFile(js_file, "utf-8")) + .replace("SUPPORTED_LANGS", JSON.stringify(Object.keys(locales))); + await fs.writeFile(js_file, content, "utf-8"); + } + + // TODO?: minify packages/backend/built/server/web/*.css +})(); diff --git a/scripts/dev-build.mjs b/scripts/dev-build.mjs index 5e8805a200..9825be3033 100644 --- a/scripts/dev-build.mjs +++ b/scripts/dev-build.mjs @@ -1,6 +1,7 @@ import path, { join } from "node:path"; import { fileURLToPath } from "node:url"; import { execa } from "execa"; +import fs from "node:fs"; (async () => { const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -32,4 +33,18 @@ import { execa } from "execa"; stdio: "inherit", } ); + + if (!fs.existsSync(join(__dirname, "/../packages/backend-rs/built/index.js"))) { + fs.copyFileSync( + join(__dirname, "/../packages/backend-rs/index.js"), + join(__dirname, "/../packages/backend-rs/built/index.js"), + ); + console.warn("backend-rs/built/index.js has not been updated (https://github.com/napi-rs/napi-rs/issues/1768)"); + } + if (!fs.existsSync(join(__dirname, "/../packages/backend-rs/built/index.d.ts"))) { + fs.copyFileSync( + join(__dirname, "/../packages/backend-rs/index.d.ts"), + join(__dirname, "/../packages/backend-rs/built/index.d.ts"), + ); + } })(); diff --git a/scripts/dev.mjs b/scripts/dev.mjs index beaa11f8e0..4fcd15753b 100644 --- a/scripts/dev.mjs +++ b/scripts/dev.mjs @@ -11,12 +11,6 @@ import { execa } from "execa"; stderr: process.stderr, }); - execa("pnpm", ["dlx", "gulp", "watch"], { - cwd: join(__dirname, "/../"), - stdout: process.stdout, - stderr: process.stderr, - }); - execa("pnpm", ["--filter", "backend", "watch"], { cwd: join(__dirname, "/../"), stdout: process.stdout,