diff --git a/.env.sample b/.env.sample
index c93af0ac..3f336a0f 100644
--- a/.env.sample
+++ b/.env.sample
@@ -1,226 +1,475 @@
# ==============================================================================
-# GENERAL ADDON CONFIGURATION
+# ESSENTIAL ADDON SETUP
# ==============================================================================
+# These are the most important settings you'll need to configure.
+
+# --- Addon Identification ---
+# Descriptive name for your addon instance.
ADDON_NAME="AIOStreams"
+# Unique identifier for your addon.
ADDON_ID="aiostreams.viren070.com"
-# Set to true to generate a deterministic addon ID based on the configuration, useful for apps like Vidi that require a different addon ID for multiple installations
-DETERMINISTIC_ADDON_ID=true
-# The port on which the addon will listen on
+
+# --- Network Configuration ---
+# The port on which the addon will listen.
+# Default: 3000
PORT=3000
-# The secret key used for encrypting the addon's configuration
-# You must use a 64 character **hex** string, use the following commands to generate one:
-# Linux: openssl rand -hex 32
-# Windows: [System.Guid]::NewGuid().ToString("N").Substring(0, 32) + [System.Guid]::NewGuid().ToString("N").Substring(0, 32)
+
+# The base URL of your addon. Highly recommended for proper functioning.
+# Used for generating installation URLs and identifying self-scraping.
+# Example: https://aiostreams.yourdomain.com
+BASE_URL=
+
+# --- Security ---
+# CRITICAL: Secret key for encrypting addon configuration.
+# MUST be a 64-character hex string.
+# Generate one using:
+# Linux/macOS: openssl rand -hex 32
+# Windows (PowerShell): -join ((0..31) | ForEach-Object { '{0:x2}' -f (Get-Random -Minimum 0 -Maximum 255) })
+# Or: [System.Guid]::NewGuid().ToString("N") + [System.Guid]::NewGuid().ToString("N") (ensure it's 64 chars)
SECRET_KEY=
-# The API key used to install and use the addon, leave empty to disable API key requirement
-# Can be set to any string
-API_KEY=
-# Controls whether the addon shows a dice emoji in its stream results
-SHOW_DIE=false
-# The log level of the addon, can be set to "debug", "info", "warn", "error"
-LOG_LEVEL=info
-# The log format of the addon, can be set to "json" or "text"
+# API key to protect your addon installation and usage.
+# Leave empty to disable password protection.
+# Can be any string.
+ADDON_PASSWORD=
+
+# --- Database ---
+# REQUIRED: The database URI for storing addon configuration.
+# Supports SQLite (simplest) or PostgreSQL.
+#
+# SQLite example (stores data in a file):
+# DATABASE_URI=sqlite://./data/db.sqlite
+# (You can change './data/db.sqlite' to your preferred path)
+#
+# PostgreSQL example:
+# DATABASE_URI=postgresql://username:password@host:port/database_name
+# (e.g., postgresql://postgres:password@localhost:5432/aiostreams)
+DATABASE_URI=sqlite://./data/db.sqlite
+
+
+# ==============================================================================
+# DEBRID & OTHER SERVICE API KEYS
+# ==============================================================================
+
+# Provide a default TMDB access token to be used for the Title Matching filter if a user does not provide any.
+TMDB_ACCESS_TOKEN=
+
+# Configure API keys for debrid services and others you plan to use.
+# 'DEFAULT_' values are pre-filled in the user's config page.
+# 'FORCED_' values override user settings and hide the option.
+
+# --- Real-Debrid ---
+DEFAULT_REALDEBRID_API_KEY=
+FORCED_REALDEBRID_API_KEY=
+
+# --- AllDebrid ---
+DEFAULT_ALLDEBRID_API_KEY=
+FORCED_ALLDEBRID_API_KEY=
+
+# --- Premiumize ---
+DEFAULT_PREMIUMIZE_API_KEY=
+FORCED_PREMIUMIZE_API_KEY=
+
+# --- Debrid-Link ---
+DEFAULT_DEBRIDLINK_API_KEY=
+FORCED_DEBRIDLINK_API_KEY=
+
+# --- Torbox ---
+DEFAULT_TORBOX_API_KEY=
+FORCED_TORBOX_API_KEY=
+
+# --- OffCloud ---
+DEFAULT_OFFCLOUD_API_KEY=
+FORCED_OFFCLOUD_API_KEY=
+DEFAULT_OFFCLOUD_EMAIL=
+FORCED_OFFCLOUD_EMAIL=
+DEFAULT_OFFCLOUD_PASSWORD=
+FORCED_OFFCLOUD_PASSWORD=
+
+# --- Put.io ---
+DEFAULT_PUTIO_CLIENT_ID=
+FORCED_PUTIO_CLIENT_ID=
+DEFAULT_PUTIO_CLIENT_SECRET=
+FORCED_PUTIO_CLIENT_SECRET=
+
+# --- EasyNews ---
+DEFAULT_EASYNEWS_USERNAME=
+FORCED_EASYNEWS_USERNAME=
+DEFAULT_EASYNEWS_PASSWORD=
+FORCED_EASYNEWS_PASSWORD=
+
+# --- EasyDebrid ---
+DEFAULT_EASYDEBRID_API_KEY=
+FORCED_EASYDEBRID_API_KEY=
+
+# --- PikPak ---
+DEFAULT_PIKPAK_EMAIL=
+FORCED_PIKPAK_EMAIL=
+DEFAULT_PIKPAK_PASSWORD=
+FORCED_PIKPAK_PASSWORD=
+
+# --- Seedr ---
+DEFAULT_SEEDR_ENCODED_TOKEN=
+FORCED_SEEDR_ENCODED_TOKEN=
+
+
+# ==============================================================================
+# CUSTOMIZATION & ACCESS CONTROL
+# ==============================================================================
+
+# --- Custom HTML ---
+# Display custom HTML at the top of the addon's configuration page.
+# Example: CUSTOM_HTML="
Welcome to my AIOStreams!
"
+CUSTOM_HTML=
+
+# --- Trusted Users ---
+# Comma-separated list of trusted UUIDs.
+# Trusted users can access features like regex filters if REGEX_FILTER_ACCESS is 'trusted'.
+# Example: TRUSTED_UUIDS=ae32f456-1234-5678-9012-345678901234,another-uuid-here
+# TRUSTED_UUIDS=
+
+# --- Regex Filter Access ---
+# Controls who can use regex filters.
+# 'none': No one can use regex filters.
+# 'trusted': Only users listed in TRUSTED_UUIDS.
+# 'all': All users (only recommended if ADDON_PASSWORD is set).
+# Default: trusted
+REGEX_FILTER_ACCESS=trusted
+
+# --- Aliased Configurations (Vanity URLs) ---
+# Create shorter, memorable installation URLs.
+# Format: aliasName1:uuid1:encryptedPassword1,aliasName2:uuid2:encryptedPassword2
+# Users can then access the addon via /stremio/u/aliasName/manifest.json
+# ALIASED_CONFIGURATIONS=
+
+
+# ==============================================================================
+# FEATURE CONTROL
+# ==============================================================================
+# Enable or disable specific addon features.
+
+# --- Self-Scraping ---
+# Prevent this AIOStreams instance from being added as an addon to itself.
+# Default: true
+DISABLE_SELF_SCRAPING=true
+
+# --- Disabled Hosts ---
+# Prevent certain hostnames from being added as addons.
+# Format: host1:reason1,host2:reason2
+# Example: DISABLED_HOSTS=torrentio.strem.fun:Blocked by Torrentio
+# DISABLED_HOSTS=
+
+# --- Disabled Addons (Marketplace) ---
+# Disable specific addons from appearing in the marketplace.
+# See https://github.com/Viren070/AIOStreams/blob/main/packages/core/src/utils/marketplace.ts for IDs.
+# Format: addonID1:reason1,addonID2:reason2
+# Example: DISABLED_ADDONS=torrentio:Blocked by Torrentio
+# DISABLED_ADDONS=
+
+# --- Disabled Services (Configuration Page) ---
+# Hide certain services (e.g., debrid services) from the configuration page.
+# Format: service1:reason1,service2:reason2
+# Example: DISABLED_SERVICES=realdebrid:Not available on this instance
+# DISABLED_SERVICES=
+
+
+# ==============================================================================
+# LOGGING
+# ==============================================================================
+
+# --- Log Level ---
+# Set the verbosity of logs. Options: "error", "warn", "info", "http", "verbose","debug", "silly"
+# Default: info
+LOG_LEVEL=http
+
+# --- Log Format ---
+# Output logs in "json" or "text" format.
+# Default: text
LOG_FORMAT=text
-# Whether to log sensitive information like API keys
+
+# --- Log Sensitive Information ---
+# Whether to include potentially sensitive info (like API keys) in logs.
+# Useful for debugging, but disable for production if concerned.
+# Default: true
LOG_SENSITIVE_INFO=true
-# ==============================================================================
# ==============================================================================
-# PROXY CONFIGURATION
+# PROXY FOR OUTGOING ADDON REQUESTS (Torrentio, etc.)
# ==============================================================================
-# The proxy URL to use for all requests made to upstream addons
-# You only need to configure this if the server you are hosting the addon on
-# is blocked by Torrentio.
-# e.g. http://warp:1080
-# from https://github.com/cmj2002/warp-docker
+# Configure a proxy for requests made *by* this AIOStreams instance *to* other addons (e.g., Torrentio).
+# Useful if your server's IP is blocked by an upstream service.
+
+# --- Addon Proxy URL ---
+# The proxy URL to use for all requests to upstream addons.
+# Example: ADDON_PROXY=http://warp:1080 (using https://github.com/cmj2002/warp-docker)
# ADDON_PROXY=
-# Optionally, configure what domains to proxy
-# Use a comma separated list of rules in the format string:boolean.
-# The later in the list, the higher the priority.
-# You can use wildcards (*) to match multiple domains
-# e.g. ADDON_PROXY_CONFIG="*:false,*.strem.fun:true"
-# This would only proxy requests to the strem.fun domain and any subdomains of it
+
+# --- Addon Proxy Configuration ---
+# Optionally, specify which domains to proxy.
+# Comma-separated list of rules: domain_pattern:boolean. Later rules have higher priority.
+# Wildcards (*) can be used.
+# Example: ADDON_PROXY_CONFIG="*:false,*.strem.fun:true" (only proxy *.strem.fun domains)
# ADDON_PROXY_CONFIG=
# ==============================================================================
-# CONFIGURATION LIMITS
-# ==============================================================================
-# The max number of addons that are allowed to be used through a single instance of the addon
-MAX_ADDONS=15
-# The maximum number of keyword filters that can be used in a single instance of the addon
-MAX_KEYWORD_FILTERS=30
-# The maximum number of regexes that can be used for sorting in a single instance of the addon
-MAX_REGEX_SORT_PATTERNS=30
-# To control the maximum size the size filter sliders can go up to in bytes
-MAX_MOVIE_SIZE=161061273600
-MAX_EPISODE_SIZE=161061273600
-# The maximum timeout that can be set for an addon through the override option
-MAX_TIMEOUT=50000
-MIN_TIMEOUT=1000
+# DEFAULT/FORCED STREAM PROXY (MediaFlow, StremThru)
# ==============================================================================
+# Configure how AIOStreams handles stream proxies like MediaFlow or StremThru for playback.
+# 'DEFAULT_' values are pre-filled. 'FORCE_' values override user settings.
-# ==============================================================================
-# MEDIAFLOW CONFIGURATION
-# ==============================================================================
-# The timeout for requesting the IP from MediaFlow
-# When we fail to get the IP from MediaFlow, no streams will be fetched and only an error message will be shown
-MEDIAFLOW_IP_TIMEOUT=30000
-# If you set a default mediaflow configuration, it will force the addon to use MediaFlow for all instances
-# A user can override the mediaflow instance to use a different one
-# DEFAULT_MEDIAFLOW_URL=
-# DEFAULT_MEDIAFLOW_API_PASSWORD=
-# DEFAULT_MEDIAFLOW_PUBLIC_IP=
-# Whether to encrypt each mediaflow URL. Improves compatability with external players.
+# --- Stream Proxy Enabled ---
+# DEFAULT_PROXY_ENABLED=true # Default state for enabling a stream proxy.
+# FORCE_PROXY_ENABLED=false # Force stream proxy on/off for all users.
+
+# --- Stream Proxy ID ---
+# 'mediaflow' or 'stremthru'
+DEFAULT_PROXY_ID=mediaflow
+# FORCE_PROXY_ID=
+
+# --- Stream Proxy URL ---
+# URL of your MediaFlow or StremThru instance.
+# DEFAULT_PROXY_URL=
+# FORCE_PROXY_URL=
+
+# --- Stream Proxy Credentials ---
+# Format: username:password
+# DEFAULT_PROXY_CREDENTIALS=
+# FORCE_PROXY_CREDENTIALS=
+
+# --- Stream Proxy Public IP ---
+# Public IP for the proxy, if needed.
+# DEFAULT_PROXY_PUBLIC_IP=
+# FORCE_PROXY_PUBLIC_IP=
+
+# --- Proxied Services ---
+# Comma-separated list of services whose streams should be proxied (e.g., realdebrid,alldebrid).
+# DEFAULT_PROXY_PROXIED_SERVICES=
+# FORCE_PROXY_PROXIED_SERVICES=
+
+# --- Disable Proxied Addons Feature ---
+# If true, proxied addons (like MediaFlow itself) won't be added as an addon.
+FORCE_PROXY_DISABLE_PROXIED_ADDONS=false
+
+# --- Encrypt Streaming URLs ---
+# Encrypt MediaFlow/StremThru URLs for better compatibility with external players.
ENCRYPT_MEDIAFLOW_URLS=true
-# ==============================================================================
-
-
-# ==============================================================================
-# STREMTHRU (PROXY) CONFIGURATION
-# ==============================================================================
-# The timeout for requests to the StremThru instance
-STREMTHRU_TIMEOUT=30000
-# If you set a default stremthru configuration, it will force the addon to use StremThru for all instances
-# A user can override the stremthru instance to use a different one
-# DEFAULT_STREMTHRU_URL=
-# The default credential used (either plain-text or base64 encoded of a username:password pair)
-# DEFAULT_STREMTHRU_CREDENTIAL=
-# Whether to optionally use a default public IP for the stremthru instance
-# DEFAULT_STREMTHRU_PUBLIC_IP=
-# Whether to encrypt each StremThru proxy URL.
ENCRYPT_STREMTHRU_URLS=true
+
# ==============================================================================
-# ADDON CONSTANTS
+# ADVANCED CONFIGURATION & LIMITS
# ==============================================================================
-# Default regex patterns for filtering and sorting
-# These are used as defaults, and can be overridden in the addon configuration page
-#
-# NOTE: You MUST provide the regex between 2 single quotes ('), not double quotes or no quotes, otherwise it will NOT work.
-#
-# Example Exclude Pattern: `/b(0neshot)\b` will exclude streams with the word "0neshot" in them
-# DEFAULT_REGEX_EXCLUDE_PATTERN=''
-# Example Include Pattern: `/b(3L)\b` will include only streams with the word "3L" in them
-# DEFAULT_REGEX_INCLUDE_PATTERN=''
-# Example Sort Patterns: `/b(3L|BiZKiT)\b \b(FraMeSToR)\b \b(TRiToN)\b` will sort streams with the word "3L" or "BiZKiT" in them, followed by "FraMeSToR", followed by "TRiToN"
-# DEFAULT_REGEX_SORT_PATTERNS=''
-
-# The default timeout for all requests. If other timeouts are not set, this will be used
+# --- General Default Timeout ---
+# Default timeout in milliseconds for all requests if not overridden by a specific timeout.
+# Default: 15000 (15 seconds)
DEFAULT_TIMEOUT=15000
-# Note: all URLs must end in a trailing slash
+# --- Configuration Limits ---
+# Maximum number of addons allowed per AIOStreams configuration.
+MAX_ADDONS=15
+# Maximum number of keyword filters per AIOStreams configuration.
+MAX_KEYWORD_FILTERS=30
+# Maximum timeout (ms) an addon can be set to via override.
+MAX_TIMEOUT=50000
+# Minimum timeout (ms) an addon can be set to via override.
+MIN_TIMEOUT=1000
+
+
+# ==============================================================================
+# RATE LIMIT CONFIGURATION
+# ==============================================================================
+# Configure rate limits to prevent abuse. Typically, defaults are fine.
+
+# --- Disable Rate Limits ---
+# Set to true to disable all rate limits (NOT RECOMMENDED).
+# Default: false
+DISABLE_RATE_LIMITS=false
+
+# Window and Max requests refer to the maximum number of requests a user can make within a specific timeframe
+
+# --- Static File Serving ---
+STATIC_RATE_LIMIT_WINDOW=5
+STATIC_RATE_LIMIT_MAX_REQUESTS=100
+
+# --- User API ---
+USER_API_RATE_LIMIT_WINDOW=5
+USER_API_RATE_LIMIT_MAX_REQUESTS=10
+
+# --- Stream API ---
+STREAM_API_RATE_LIMIT_WINDOW=5
+STREAM_API_RATE_LIMIT_MAX_REQUESTS=10
+
+# --- Format API ---
+FORMAT_API_RATE_LIMIT_WINDOW=5
+FORMAT_API_RATE_LIMIT_MAX_REQUESTS=15
+
+# --- Catalog API ---
+CATALOG_API_RATE_LIMIT_WINDOW=5
+CATALOG_API_RATE_LIMIT_MAX_REQUESTS=5
+
+# --- Stremio Stream ---
+STREMIO_STREAM_RATE_LIMIT_WINDOW=5
+STREMIO_STREAM_RATE_LIMIT_MAX_REQUESTS=10
+
+# --- Stremio Catalog ---
+STREMIO_CATALOG_RATE_LIMIT_WINDOW=5
+STREMIO_CATALOG_RATE_LIMIT_MAX_REQUESTS=10
+
+
+# ==============================================================================
+# INACTIVE USER PRUNING
+# ==============================================================================
+# Automatically prune (delete) inactive user configurations.
+
+# --- Prune Interval ---
+# How often to check for inactive users, in seconds.
+# Default: 86400 (1 day)
+PRUNE_INTERVAL=86400
+
+# --- Prune Max Inactivity Days ---
+# Maximum days of inactivity before a user's configuration is pruned.
+# Default: 30
+PRUNE_MAX_DAYS=30
+
+
+# ==============================================================================
+# EXTERNAL ADDON SERVICE URLs & TIMEOUTS
+# ==============================================================================
+# URLs and default timeouts for various external Stremio addons that AIOStreams can integrate with.
+# Change these if you use self-hosted versions or if defaults become outdated.
# ----------- COMET ------------
COMET_URL=https://comet.elfhosted.com/
-# The default timeout for all requests to the Comet API. If left empty, either the DEFAULT_TIMEOUT or the overriden timeout will be used
-# DEFAULT_COMET_TIMOUT=
-# The following environment variables should only be set if you are using an internal URL for 'COMET_URL' e.g. http://comet:3000/
-# and want the comet streams to be accessible from outside the network
-# i.e. you would set these to the public URL of the comet instance
-# Do not uncomment these if you don't want to use them, as these accept empty strings and your comet streams will NOT work
-
-# Example scenarios:
-# 1. Your COMET_URL is an internal URL (e.g. http://comet:3000), you would need to set FORCE_COMET_HOSTNAME to your publicly accessible host, set FORCE_COMET_PROTOCOL as needed
-# and make sure to set FORCE_COMET_PROTOCOL to an empty value
-# 2. Same as scenario 1, but you are using mediaflow proxy on the same docker network. In this case, it is better for MediaFlow proxy to use the internal URL so leave these
-# commented out.
-# 3. You set COMET_URL to a publicly accessible URL. No further actions are required.
+# DEFAULT_COMET_TIMEOUT=
+# Advanced: Override Comet hostname/port/protocol if COMET_URL is internal but needs to be public-facing.
+# Only uncomment and set if needed. Usually, leave these commented.
# FORCE_COMET_HOSTNAME=
# FORCE_COMET_PORT=
-# FORCE_COMET_PROTOCOL=
-# -------------------------------------
+# FORCE_COMET_PROTOCOL= # e.g., https
# ----------- MEDIAFUSION ------------
MEDIAFUSION_URL=https://mediafusion.elfhosted.com/
# DEFAULT_MEDIAFUSION_TIMEOUT=
-# The timeout applied to the /encrypt-user-data endpoint of MediaFusion when auto generating the configuration
-MEDIAFUSION_CONFIG_TIMEOUT=5000
-# If you are using a self hosted instance of MediaFusion protected with a 'API_PASSWORD', you must provide it here
-# If you want to be able to make use of the auto configuration. If you are planning on overriding the URL at the config page, you can leave this empty
+MEDIAFUSION_CONFIG_TIMEOUT=5000 # Timeout (ms) for /encrypt-user-data endpoint.
+# API Password for self-hosted MediaFusion (for auto-configuration).
# MEDIAFUSION_API_PASSWORD=
-# -------------------------------------
# ----------- JACKETTIO -------------
JACKETTIO_URL=https://jackettio.elfhosted.com/
-# The default indexers used when auto generating the configuration. Change if using a custom Jackettio instance, and you have different indexers
-DEFAULT_JACKETTIO_INDEXERS=["bitsearch", "eztv", "thepiratebay", "therarbg", "yts"]
# DEFAULT_JACKETTIO_TIMEOUT=
-# The default URL used for the stremthru instance.
+# Default indexers for auto-configuration with Jackettio.
+DEFAULT_JACKETTIO_INDEXERS='["bitsearch", "eztv", "thepiratebay", "therarbg", "yts"]'
+# Default StremThru URL used by Jackettio.
DEFAULT_JACKETTIO_STREMTHRU_URL=https://stremthru.13377001.xyz
-# You may also provide a selfhosted instance of StremThru here.
+# Self-hosted StremThru for Jackettio:
# DEFAULT_JACKETTIO_STREMTHRU_URL=http://stremthru:8080
-
-# These values work the same as the comet ones, but for Jackettio
+# Advanced: Override Jackettio hostname/port/protocol (similar to Comet).
# FORCE_JACKETTIO_HOSTNAME=
# FORCE_JACKETTIO_PORT=
# FORCE_JACKETTIO_PROTOCOL=
-# -------------------------------------
-
-# ---------- STREMIO-JACKETT ----------
-STREMIO_JACKETT_URL=https://stremio-jackett.elfhosted.com/
-# If using a self hosted instance, provide the Jackett URL and API key here
-# DEFAULT_STREMIO_JACKETT_JACKETT_URL=
-# DEFAULT_STREMIO_JACKETT_JACKETT_API_KEY=
-# The default API key used in Stremio Jackett configurations.
-# DEFAULT_STREMIO_JACKETT_TMDB_API_KEY=
-# DEFAULT_STREMIO_JACKETT_TIMEOUT=
-# -------------------------------------
-
# --------- STREMTHRU-STORE ---------
STREMTHRU_STORE_URL=https://stremthru.elfhosted.com/stremio/store/
# DEFAULT_STREMTHRU_STORE_TIMEOUT=
-# --------------------------------------
+
+# --------- STREMTHRU-TORZ -----
+STREMTHRU_TORZ_URL=https://stremthru.elfhosted.com/stremio/torz/
+# DEFAULT_STREMTHRU_TORZ_TIMEOUT=
# --------- EASYNEWS+ ADDON ---------
EASYNEWS_PLUS_URL=https://b89262c192b0-stremio-easynews-addon.baby-beamup.club/
# DEFAULT_EASYNEWS_PLUS_TIMEOUT=
-# -------------------------------------
# -------- EASYNEWS++ ADDON ---------
EASYNEWS_PLUS_PLUS_URL=https://easynews-cloudflare-worker.jqrw92fchz.workers.dev/
# DEFAULT_EASYNEWS_PLUS_PLUS_TIMEOUT=
-# -------------------------------------
+
+# --------- STREAMFUSION ---------
+STREAMFUSION_URL=https://stream-fusion.stremiofr.com/
+# DEFAULT_STREAMFUSION_TIMEOUT=
+
+# --------- MARVEL UNIVERSE ---------
+MARVEL_UNIVERSE_URL=https://addon-marvel.onrender.com/
+# DEFAULT_MARVEL_UNIVERSE_TIMEOUT=
+
+# --------- DC UNIVERSE ---------
+DC_UNIVERSE_URL=https://addon-dc-cq85.onrender.com/
+# DEFAULT_DC_UNIVERSE_TIMEOUT=
+
+# --------- STAR WARS UNIVERSE ---------
+STAR_WARS_UNIVERSE_URL=https://addon-star-wars-u9e3.onrender.com/
+# DEFAULT_STAR_WARS_UNIVERSE_TIMEOUT=
+
+# --------- ANIME KITSU ---------
+ANIME_KITSU_URL=https://anime-kitsu.strem.fun/
+# DEFAULT_ANIME_KITSU_TIMEOUT=
+
+# --------- NUVIOSTREAMS ---------
+NUVIOSTREAMS_URL=https://nuviostreams.hayd.uk/
+# DEFAULT_NUVIOSTREAMS_TIMEOUT=
+
+# --------- TMDB COLLECTIONS ---------
+TMDB_COLLECTIONS_URL=https://61ab9c85a149-tmdb-collections.baby-beamup.club/
+# DEFAULT_TMDB_COLLECTIONS_TIMEOUT=
# ----------- TORRENTIO -------------
TORRENTIO_URL=https://torrentio.strem.fun/
# DEFAULT_TORRENTIO_TIMEOUT=
-# -------------------------------------
# -------- ORION STREMIO ADDON --------
ORION_STREMIO_ADDON_URL=https://5a0d1888fa64-orion.baby-beamup.club/
# DEFAULT_ORION_STREMIO_ADDON_TIMEOUT=
-# -------------------------------------
# ------------ PEERFLIX --------------
PEERFLIX_URL=https://peerflix-addon.onrender.com/
# DEFAULT_PEERFLIX_TIMEOUT=
-# -------------------------------------
# -------- TORBOX STREMIO ADDON --------
TORBOX_STREMIO_URL=https://stremio.torbox.app/
# DEFAULT_TORBOX_STREMIO_TIMEOUT=
-# --------------------------------------
-# -------- EASYNEWS ADDON --------
+# -------- EASYNEWS ADDON (Standalone) --------
EASYNEWS_URL=https://ea627ddf0ee7-easynews.baby-beamup.club/
# DEFAULT_EASYNEWS_TIMEOUT=
-# --------------------------------------
# ------------ DEBRIDIO -----------
DEBRIDIO_URL=https://debridio.adobotec.com/
# DEFAULT_DEBRIDIO_TIMEOUT=
-# --------------------------------------
+
+# ------------ DEBRIDIO TVDB ------------
+DEBRIDIO_TVDB_URL=https://tvdb-addon.debridio.com/
+# DEFAULT_DEBRIDIO_TVDB_TIMEOUT=
+
+# ------------ DEBRIDIO TMDB ------------
+DEBRIDIO_TMDB_URL=https://tmdb-addon.debridio.com/
+# DEFAULT_DEBRIDIO_TMDB_TIMEOUT=
+
+# ------------ DEBRIDIO TV ------------
+DEBRIDIO_TV_URL=https://tv-addon.debridio.com/
+# DEFAULT_DEBRIDIO_TV_TIMEOUT=
+
+# ------------ DEBRIDIO WATCHTOWER ------------
+DEBRIDIO_WATCHTOWER_URL=https://wt-addon.debridio.com/
+# DEFAULT_DEBRIDIO_WATCHTOWER_TIMEOUT=
+
+# ------------ OPENSUBTITLES V3 ------------
+OPENSUBTITLES_URL=https://opensubtitles-v3.strem.io/
+# DEFAULT_OPENSUBTITLES_TIMEOUT=
+
+# ------------ TORRENT CATALOGS ------------
+TORRENT_CATALOGS_URL=https://torrent-catalogs.strem.fun/
+# DEFAULT_TORRENT_CATALOGS_TIMEOUT=
+
+# ------------ RPDB CATALOGS ------------
+RPDB_CATALOGS_URL=https://1fe84bc728af-rpdb.baby-beamup.club/
+# DEFAULT_RPDB_CATALOGS_TIMEOUT=
# ------------- DMM Cast ----------------
# DEFAULT_DMM_CAST_TIMEOUT=
-# --------------------------------------
# -------------- STREMIO GDRIVE ----------------
# DEFAULT_STREMIO_GDRIVE_TIMEOUT=
-# --------------------------------------
# ==============================================================================
\ No newline at end of file
diff --git a/.github/workflows/deploy-docker.yml b/.github/workflows/deploy-docker.yml
index ba0a3771..ea9ed486 100644
--- a/.github/workflows/deploy-docker.yml
+++ b/.github/workflows/deploy-docker.yml
@@ -53,9 +53,11 @@ jobs:
if [[ "$(git rev-parse origin/main)" = "$(git rev-parse "${INPUT_REF}")" ]]; then
TAGS="${TAGS} latest"
fi
+ CHANNEL="stable"
;;
[0-9]*.[0-9]*.[0-9]*-nightly)
TAGS="${INPUT_REF} nightly"
+ CHANNEL="nightly"
;;
*)
echo "Invalid Input Ref: ${INPUT_REF}"
@@ -76,8 +78,19 @@ jobs:
echo EOF
} >> "${GITHUB_ENV}"
+ echo "CHANNEL=${CHANNEL}" >> "${GITHUB_ENV}"
+
cat "${GITHUB_ENV}"
+ - name: Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - name: Generate metadata
+ run: |
+ node scripts/generateMetadata.js --channel=${{env.CHANNEL}}
+
- name: Build & Push
uses: docker/build-push-action@v6
with:
diff --git a/.gitignore b/.gitignore
index 933bdda2..4150dcb2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,6 @@ out/
.next/
next-env.d.ts
.wrangler/
-.env
\ No newline at end of file
+.env
+metadata.json
+data/
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index b146be96..70a6a5d3 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -7,13 +7,9 @@ COPY LICENSE ./
# Copy the relevant package.json and package-lock.json files.
COPY package*.json ./
-COPY packages/formatters/package*.json ./packages/formatters/
-COPY packages/parser/package*.json ./packages/parser/
-COPY packages/types/package*.json ./packages/types/
-COPY packages/wrappers/package*.json ./packages/wrappers/
-COPY packages/addon/package*.json ./packages/addon/
+COPY packages/server/package*.json ./packages/server/
+COPY packages/core/package*.json ./packages/core/
COPY packages/frontend/package*.json ./packages/frontend/
-COPY packages/utils/package*.json ./packages/utils/
# Install dependencies.
RUN npm install
@@ -21,13 +17,12 @@ RUN npm install
# Copy source files.
COPY tsconfig.*json ./
-COPY packages/addon ./packages/addon
-COPY packages/formatters ./packages/formatters
-COPY packages/parser ./packages/parser
-COPY packages/types ./packages/types
-COPY packages/wrappers ./packages/wrappers
+COPY packages/server ./packages/server
+COPY packages/core ./packages/core
COPY packages/frontend ./packages/frontend
-COPY packages/utils ./packages/utils
+COPY scripts ./scripts
+COPY resources ./resources
+
# Build the project.
RUN npm run build
@@ -43,25 +38,21 @@ WORKDIR /app
# The package.json files must be copied as well for NPM workspace symlinks between local packages to work.
COPY --from=builder /build/package*.json /build/LICENSE ./
-COPY --from=builder /build/packages/addon/package.*json ./packages/addon/
+COPY --from=builder /build/packages/core/package.*json ./packages/core/
COPY --from=builder /build/packages/frontend/package.*json ./packages/frontend/
-COPY --from=builder /build/packages/formatters/package.*json ./packages/formatters/
-COPY --from=builder /build/packages/parser/package.*json ./packages/parser/
-COPY --from=builder /build/packages/types/package.*json ./packages/types/
-COPY --from=builder /build/packages/wrappers/package.*json ./packages/wrappers/
-COPY --from=builder /build/packages/utils/package.*json ./packages/utils/
+COPY --from=builder /build/packages/server/package.*json ./packages/server/
-
-COPY --from=builder /build/packages/addon/dist ./packages/addon/dist
+COPY --from=builder /build/packages/core/dist ./packages/core/dist
COPY --from=builder /build/packages/frontend/out ./packages/frontend/out
-COPY --from=builder /build/packages/formatters/dist ./packages/formatters/dist
-COPY --from=builder /build/packages/parser/dist ./packages/parser/dist
-COPY --from=builder /build/packages/types/dist ./packages/types/dist
-COPY --from=builder /build/packages/wrappers/dist ./packages/wrappers/dist
-COPY --from=builder /build/packages/utils/dist ./packages/utils/dist
+COPY --from=builder /build/packages/server/dist ./packages/server/dist
+
+COPY --from=builder /build/resources ./resources
COPY --from=builder /build/node_modules ./node_modules
-EXPOSE 3000
+HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
+ CMD wget --no-verbose --tries=1 --spider http://localhost:$PORT/api/v1/status || exit 1
-ENTRYPOINT ["npm", "run", "start:addon"]
\ No newline at end of file
+EXPOSE $PORT
+
+ENTRYPOINT ["npm", "run", "start"]
\ No newline at end of file
diff --git a/compose.yaml b/compose.yaml
index ae53770f..112138f9 100644
--- a/compose.yaml
+++ b/compose.yaml
@@ -7,8 +7,10 @@ services:
- 3000:3000
env_file:
- .env
+ volumes:
+ - ./data:/app/data
healthcheck:
- test: wget -qO- http://localhost:3000/health
+ test: wget -qO- http://localhost:3000/api/v1/status
interval: 1m
timeout: 10s
retries: 5
diff --git a/package-lock.json b/package-lock.json
index 269afe78..9d19f173 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,16 +11,10 @@
"workspaces": [
"packages/*"
],
- "dependencies": {
- "super-regex": "^1.0.0",
- "undici": "^7.2.3"
- },
"devDependencies": {
- "@types/node": "^20.14.10",
- "beamup-cli": "^1.3.0",
- "commit-and-tag-version": "^12.5.0",
"cross-env": "^7.0.3",
"prettier": "^3.3.2",
+ "ts-node": "^10.9.2",
"tsx": "^4.16.2",
"typescript": "^5.5.3",
"vitest": "^2.1.5"
@@ -29,44 +23,51 @@
"node": ">=20.0.0"
}
},
- "node_modules/@aiostreams/addon": {
- "resolved": "packages/addon",
- "link": true
- },
- "node_modules/@aiostreams/cloudflare-worker": {
- "resolved": "packages/cloudflare-worker",
- "link": true
- },
- "node_modules/@aiostreams/formatters": {
- "resolved": "packages/formatters",
+ "node_modules/@aiostreams/core": {
+ "resolved": "packages/core",
"link": true
},
"node_modules/@aiostreams/frontend": {
"resolved": "packages/frontend",
"link": true
},
- "node_modules/@aiostreams/parser": {
- "resolved": "packages/parser",
+ "node_modules/@aiostreams/server": {
+ "resolved": "packages/server",
"link": true
},
- "node_modules/@aiostreams/types": {
- "resolved": "packages/types",
- "link": true
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
},
- "node_modules/@aiostreams/utils": {
- "resolved": "packages/utils",
- "link": true
- },
- "node_modules/@aiostreams/wrappers": {
- "resolved": "packages/wrappers",
- "link": true
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
},
"node_modules/@asamuzakjp/css-color": {
"version": "3.1.1",
- "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.1.1.tgz",
- "integrity": "sha512-hpRD68SV2OMcZCsrbdkccTw5FXjNDLo5OuqSHyHZfwweGsDWZwDJ2+gONyNAbazZclobMirACLw0lk8WVxIqxA==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"@csstools/css-calc": "^2.1.2",
"@csstools/css-color-parser": "^3.0.8",
@@ -77,285 +78,13 @@
},
"node_modules/@asamuzakjp/css-color/node_modules/lru-cache": {
"version": "10.4.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
- "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"dev": true,
- "license": "ISC"
- },
- "node_modules/@babel/code-frame": {
- "version": "7.26.2",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
- "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.25.9",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.0.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/generator": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz",
- "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==",
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.26.3",
- "@babel/types": "^7.26.3",
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.25",
- "jsesc": "^3.0.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.25",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
- "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
- "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
- "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
- "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz",
- "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.26.3"
- },
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/runtime": {
- "version": "7.26.0",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
- "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
- "license": "MIT",
- "dependencies": {
- "regenerator-runtime": "^0.14.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
- "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.25.9",
- "@babel/parser": "^7.25.9",
- "@babel/types": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.26.4",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz",
- "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.26.2",
- "@babel/generator": "^7.26.3",
- "@babel/parser": "^7.26.3",
- "@babel/template": "^7.25.9",
- "@babel/types": "^7.26.3",
- "debug": "^4.3.1",
- "globals": "^11.1.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse/node_modules/globals": {
- "version": "11.12.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
- "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/types": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz",
- "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@cloudflare/kv-asset-handler": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.4.tgz",
- "integrity": "sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==",
- "dev": true,
- "license": "MIT OR Apache-2.0",
- "dependencies": {
- "mime": "^3.0.0"
- },
- "engines": {
- "node": ">=16.13"
- }
- },
- "node_modules/@cloudflare/kv-asset-handler/node_modules/mime": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
- "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/@cloudflare/workerd-darwin-64": {
- "version": "1.20241230.0",
- "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20241230.0.tgz",
- "integrity": "sha512-BZHLg4bbhNQoaY1Uan81O3FV/zcmWueC55juhnaI7NAobiQth9RppadPNpxNAmS9fK2mR5z8xrwMQSQrHmztyQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0",
+ "license": "ISC",
"optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/@cloudflare/workerd-darwin-arm64": {
- "version": "1.20241230.0",
- "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20241230.0.tgz",
- "integrity": "sha512-lllxycj7EzYoJ0VOJh8M3palUgoonVrILnzGrgsworgWlIpgjfXGS7b41tEGCw6AxSxL9prmTIGtfSPUvn/rjg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/@cloudflare/workerd-linux-64": {
- "version": "1.20241230.0",
- "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20241230.0.tgz",
- "integrity": "sha512-Y3mHcW0KghOmWdNZyHYpEOG4Ba/ga8tht5vj1a+WXfagEjMO8Y98XhZUlCaYa9yB7Wh5jVcK5LM2jlO/BLgqpA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/@cloudflare/workerd-linux-arm64": {
- "version": "1.20241230.0",
- "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20241230.0.tgz",
- "integrity": "sha512-IAjhsWPlHzhhkJ6I49sDG6XfMnhPvv0szKGXxTWQK/IWMrbGdHm4RSfNKBSoLQm67jGMIzbmcrX9UIkms27Y1g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/@cloudflare/workerd-windows-64": {
- "version": "1.20241230.0",
- "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20241230.0.tgz",
- "integrity": "sha512-y5SPIk9iOb2gz+yWtHxoeMnjPnkYQswiCJ480oHC6zexnJLlKTpcmBCjDH1nWCT4pQi8F25gaH8thgElf4NvXQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "Apache-2.0",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/@cloudflare/workers-types": {
- "version": "4.20250109.0",
- "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20250109.0.tgz",
- "integrity": "sha512-Y1zgSaEOOevl9ORpzgMcm4j535p3nK2lrblHHvYM2yxR50SBKGh+wvkRFAIxWRfjUGZEU+Fp6923EGioDBbobA==",
- "dev": true,
- "license": "MIT OR Apache-2.0"
+ "peer": true
},
"node_modules/@colors/colors": {
"version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
- "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
"license": "MIT",
"engines": {
"node": ">=0.1.90"
@@ -374,10 +103,19 @@
"node": ">=12"
}
},
+ "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
"node_modules/@csstools/color-helpers": {
"version": "5.0.2",
- "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.2.tgz",
- "integrity": "sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==",
"dev": true,
"funding": [
{
@@ -390,14 +128,14 @@
}
],
"license": "MIT-0",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/@csstools/css-calc": {
"version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.2.tgz",
- "integrity": "sha512-TklMyb3uBB28b5uQdxjReG4L80NxAqgrECqLZFQbyLekwwlcDDS8r3f07DKqeo8C4926Br0gf/ZDe17Zv4wIuw==",
"dev": true,
"funding": [
{
@@ -410,6 +148,8 @@
}
],
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=18"
},
@@ -420,8 +160,6 @@
},
"node_modules/@csstools/css-color-parser": {
"version": "3.0.8",
- "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.8.tgz",
- "integrity": "sha512-pdwotQjCCnRPuNi06jFuP68cykU1f3ZWExLe/8MQ1LOs8Xq+fTkYgd+2V8mWUWMrOn9iS2HftPVaMZDaXzGbhQ==",
"dev": true,
"funding": [
{
@@ -434,6 +172,8 @@
}
],
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"@csstools/color-helpers": "^5.0.2",
"@csstools/css-calc": "^2.1.2"
@@ -448,8 +188,6 @@
},
"node_modules/@csstools/css-parser-algorithms": {
"version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz",
- "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==",
"dev": true,
"funding": [
{
@@ -462,6 +200,8 @@
}
],
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=18"
},
@@ -471,8 +211,6 @@
},
"node_modules/@csstools/css-tokenizer": {
"version": "3.0.3",
- "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz",
- "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==",
"dev": true,
"funding": [
{
@@ -485,14 +223,14 @@
}
],
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/@dabh/diagnostics": {
"version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
- "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==",
"license": "MIT",
"dependencies": {
"colorspace": "1.1.x",
@@ -500,558 +238,108 @@
"kuler": "^2.0.0"
}
},
+ "node_modules/@dnd-kit/accessibility": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz",
+ "integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@dnd-kit/core": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
+ "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@dnd-kit/accessibility": "^3.1.1",
+ "@dnd-kit/utilities": "^3.2.2",
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@dnd-kit/modifiers": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-9.0.0.tgz",
+ "integrity": "sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw==",
+ "license": "MIT",
+ "dependencies": {
+ "@dnd-kit/utilities": "^3.2.2",
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "@dnd-kit/core": "^6.3.0",
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@dnd-kit/sortable": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz",
+ "integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==",
+ "license": "MIT",
+ "dependencies": {
+ "@dnd-kit/utilities": "^3.2.2",
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "@dnd-kit/core": "^6.3.0",
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@dnd-kit/utilities": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz",
+ "integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@emnapi/core": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz",
+ "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.0.2",
+ "tslib": "^2.4.0"
+ }
+ },
"node_modules/@emnapi/runtime": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz",
- "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==",
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz",
+ "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==",
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
- "node_modules/@emotion/babel-plugin": {
- "version": "11.13.5",
- "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz",
- "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==",
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz",
+ "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==",
+ "dev": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
- "@babel/helper-module-imports": "^7.16.7",
- "@babel/runtime": "^7.18.3",
- "@emotion/hash": "^0.9.2",
- "@emotion/memoize": "^0.9.0",
- "@emotion/serialize": "^1.3.3",
- "babel-plugin-macros": "^3.1.0",
- "convert-source-map": "^1.5.0",
- "escape-string-regexp": "^4.0.0",
- "find-root": "^1.1.0",
- "source-map": "^0.5.7",
- "stylis": "4.2.0"
- }
- },
- "node_modules/@emotion/babel-plugin/node_modules/source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/@emotion/cache": {
- "version": "11.14.0",
- "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz",
- "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==",
- "license": "MIT",
- "dependencies": {
- "@emotion/memoize": "^0.9.0",
- "@emotion/sheet": "^1.4.0",
- "@emotion/utils": "^1.4.2",
- "@emotion/weak-memoize": "^0.4.0",
- "stylis": "4.2.0"
- }
- },
- "node_modules/@emotion/hash": {
- "version": "0.9.2",
- "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
- "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==",
- "license": "MIT"
- },
- "node_modules/@emotion/memoize": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz",
- "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==",
- "license": "MIT"
- },
- "node_modules/@emotion/react": {
- "version": "11.14.0",
- "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
- "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.18.3",
- "@emotion/babel-plugin": "^11.13.5",
- "@emotion/cache": "^11.14.0",
- "@emotion/serialize": "^1.3.3",
- "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
- "@emotion/utils": "^1.4.2",
- "@emotion/weak-memoize": "^0.4.0",
- "hoist-non-react-statics": "^3.3.1"
- },
- "peerDependencies": {
- "react": ">=16.8.0"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@emotion/serialize": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz",
- "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==",
- "license": "MIT",
- "dependencies": {
- "@emotion/hash": "^0.9.2",
- "@emotion/memoize": "^0.9.0",
- "@emotion/unitless": "^0.10.0",
- "@emotion/utils": "^1.4.2",
- "csstype": "^3.0.2"
- }
- },
- "node_modules/@emotion/sheet": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz",
- "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==",
- "license": "MIT"
- },
- "node_modules/@emotion/unitless": {
- "version": "0.10.0",
- "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz",
- "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==",
- "license": "MIT"
- },
- "node_modules/@emotion/use-insertion-effect-with-fallbacks": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz",
- "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==",
- "license": "MIT",
- "peerDependencies": {
- "react": ">=16.8.0"
- }
- },
- "node_modules/@emotion/utils": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz",
- "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==",
- "license": "MIT"
- },
- "node_modules/@emotion/weak-memoize": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
- "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==",
- "license": "MIT"
- },
- "node_modules/@esbuild-plugins/node-globals-polyfill": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.2.3.tgz",
- "integrity": "sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==",
- "dev": true,
- "license": "ISC",
- "peerDependencies": {
- "esbuild": "*"
- }
- },
- "node_modules/@esbuild-plugins/node-modules-polyfill": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.2.2.tgz",
- "integrity": "sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "escape-string-regexp": "^4.0.0",
- "rollup-plugin-node-polyfills": "^0.2.1"
- },
- "peerDependencies": {
- "esbuild": "*"
- }
- },
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz",
- "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz",
- "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz",
- "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz",
- "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz",
- "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz",
- "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz",
- "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz",
- "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz",
- "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz",
- "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz",
- "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz",
- "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz",
- "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz",
- "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz",
- "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz",
- "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz",
- "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz",
- "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-arm64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz",
- "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz",
- "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz",
- "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz",
- "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz",
- "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
+ "tslib": "^2.4.0"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.23.1",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz",
- "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==",
"cpu": [
"x64"
],
@@ -1066,9 +354,9 @@
}
},
"node_modules/@eslint-community/eslint-utils": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
- "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==",
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
+ "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1108,13 +396,13 @@
}
},
"node_modules/@eslint/config-array": {
- "version": "0.19.1",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz",
- "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==",
+ "version": "0.20.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz",
+ "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/object-schema": "^2.1.5",
+ "@eslint/object-schema": "^2.1.6",
"debug": "^4.3.1",
"minimatch": "^3.1.2"
},
@@ -1122,10 +410,20 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz",
+ "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
"node_modules/@eslint/core": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz",
- "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==",
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz",
+ "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -1136,9 +434,9 @@
}
},
"node_modules/@eslint/eslintrc": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz",
- "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
+ "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1159,20 +457,36 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/@eslint/js": {
- "version": "9.17.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz",
- "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==",
+ "version": "9.27.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz",
+ "integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
}
},
"node_modules/@eslint/object-schema": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz",
- "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==",
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
+ "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -1180,53 +494,109 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.2.4",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz",
- "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==",
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz",
+ "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
+ "@eslint/core": "^0.14.0",
"levn": "^0.4.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@fastify/busboy": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz",
- "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14"
- }
- },
"node_modules/@floating-ui/core": {
- "version": "1.6.9",
- "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.9.tgz",
- "integrity": "sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.0.tgz",
+ "integrity": "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==",
"license": "MIT",
"dependencies": {
"@floating-ui/utils": "^0.2.9"
}
},
"node_modules/@floating-ui/dom": {
- "version": "1.6.13",
- "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz",
- "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.0.tgz",
+ "integrity": "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==",
"license": "MIT",
"dependencies": {
- "@floating-ui/core": "^1.6.0",
+ "@floating-ui/core": "^1.7.0",
"@floating-ui/utils": "^0.2.9"
}
},
+ "node_modules/@floating-ui/react": {
+ "version": "0.26.28",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz",
+ "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.1.2",
+ "@floating-ui/utils": "^0.2.8",
+ "tabbable": "^6.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz",
+ "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/dom": "^1.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
"node_modules/@floating-ui/utils": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz",
"integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==",
"license": "MIT"
},
+ "node_modules/@gar/promisify": {
+ "version": "1.1.3",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/@headlessui/react": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.4.tgz",
+ "integrity": "sha512-lz+OGcAH1dK93rgSMzXmm1qKOJkBUqZf1L4M8TWLNplftQD3IkoEDdUFNfAn4ylsN6WOTVtWaLmvmaHOUk1dTA==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react": "^0.26.16",
+ "@react-aria/focus": "^3.20.2",
+ "@react-aria/interactions": "^3.25.0",
+ "@tanstack/react-virtual": "^3.13.9",
+ "use-sync-external-store": "^1.5.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": "^18 || ^19 || ^19.0.0-rc",
+ "react-dom": "^18 || ^19 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/@headlessui/tailwindcss": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@headlessui/tailwindcss/-/tailwindcss-0.2.2.tgz",
+ "integrity": "sha512-xNe42KjdyA4kfUKLLPGzME9zkH7Q3rOZ5huFihWNWOQFxnItxPB3/67yBI8/qBfY8nwBRx5GHn4VprsoluVMGw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "tailwindcss": "^3.0 || ^4.0"
+ }
+ },
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -1280,9 +650,9 @@
}
},
"node_modules/@humanwhocodes/retry": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz",
- "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==",
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -1293,20 +663,10 @@
"url": "https://github.com/sponsors/nzakas"
}
},
- "node_modules/@hutson/parse-repository-url": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz",
- "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@img/sharp-darwin-arm64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",
- "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==",
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.1.tgz",
+ "integrity": "sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==",
"cpu": [
"arm64"
],
@@ -1322,13 +682,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-darwin-arm64": "1.0.4"
+ "@img/sharp-libvips-darwin-arm64": "1.1.0"
}
},
"node_modules/@img/sharp-darwin-x64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz",
- "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==",
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.1.tgz",
+ "integrity": "sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==",
"cpu": [
"x64"
],
@@ -1344,13 +704,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-darwin-x64": "1.0.4"
+ "@img/sharp-libvips-darwin-x64": "1.1.0"
}
},
"node_modules/@img/sharp-libvips-darwin-arm64": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz",
- "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz",
+ "integrity": "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==",
"cpu": [
"arm64"
],
@@ -1364,9 +724,9 @@
}
},
"node_modules/@img/sharp-libvips-darwin-x64": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz",
- "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz",
+ "integrity": "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==",
"cpu": [
"x64"
],
@@ -1380,9 +740,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-arm": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz",
- "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz",
+ "integrity": "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==",
"cpu": [
"arm"
],
@@ -1396,9 +756,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-arm64": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz",
- "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz",
+ "integrity": "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==",
"cpu": [
"arm64"
],
@@ -1411,10 +771,26 @@
"url": "https://opencollective.com/libvips"
}
},
+ "node_modules/@img/sharp-libvips-linux-ppc64": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz",
+ "integrity": "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
"node_modules/@img/sharp-libvips-linux-s390x": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz",
- "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz",
+ "integrity": "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==",
"cpu": [
"s390x"
],
@@ -1428,9 +804,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-x64": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz",
- "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz",
+ "integrity": "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==",
"cpu": [
"x64"
],
@@ -1444,9 +820,9 @@
}
},
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz",
- "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz",
+ "integrity": "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==",
"cpu": [
"arm64"
],
@@ -1460,9 +836,9 @@
}
},
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz",
- "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz",
+ "integrity": "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==",
"cpu": [
"x64"
],
@@ -1476,9 +852,9 @@
}
},
"node_modules/@img/sharp-linux-arm": {
- "version": "0.33.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz",
- "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==",
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.1.tgz",
+ "integrity": "sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==",
"cpu": [
"arm"
],
@@ -1494,13 +870,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-arm": "1.0.5"
+ "@img/sharp-libvips-linux-arm": "1.1.0"
}
},
"node_modules/@img/sharp-linux-arm64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz",
- "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.1.tgz",
+ "integrity": "sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==",
"cpu": [
"arm64"
],
@@ -1516,13 +892,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-arm64": "1.0.4"
+ "@img/sharp-libvips-linux-arm64": "1.1.0"
}
},
"node_modules/@img/sharp-linux-s390x": {
- "version": "0.33.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz",
- "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==",
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.1.tgz",
+ "integrity": "sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==",
"cpu": [
"s390x"
],
@@ -1538,13 +914,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-s390x": "1.0.4"
+ "@img/sharp-libvips-linux-s390x": "1.1.0"
}
},
"node_modules/@img/sharp-linux-x64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz",
- "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==",
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.1.tgz",
+ "integrity": "sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==",
"cpu": [
"x64"
],
@@ -1560,13 +936,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-x64": "1.0.4"
+ "@img/sharp-libvips-linux-x64": "1.1.0"
}
},
"node_modules/@img/sharp-linuxmusl-arm64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz",
- "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==",
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.1.tgz",
+ "integrity": "sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==",
"cpu": [
"arm64"
],
@@ -1582,13 +958,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-arm64": "1.0.4"
+ "@img/sharp-libvips-linuxmusl-arm64": "1.1.0"
}
},
"node_modules/@img/sharp-linuxmusl-x64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz",
- "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==",
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.1.tgz",
+ "integrity": "sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==",
"cpu": [
"x64"
],
@@ -1604,20 +980,20 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-x64": "1.0.4"
+ "@img/sharp-libvips-linuxmusl-x64": "1.1.0"
}
},
"node_modules/@img/sharp-wasm32": {
- "version": "0.33.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz",
- "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==",
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.1.tgz",
+ "integrity": "sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==",
"cpu": [
"wasm32"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
"optional": true,
"dependencies": {
- "@emnapi/runtime": "^1.2.0"
+ "@emnapi/runtime": "^1.4.0"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
@@ -1627,9 +1003,9 @@
}
},
"node_modules/@img/sharp-win32-ia32": {
- "version": "0.33.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz",
- "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==",
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.1.tgz",
+ "integrity": "sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==",
"cpu": [
"ia32"
],
@@ -1646,9 +1022,9 @@
}
},
"node_modules/@img/sharp-win32-x64": {
- "version": "0.33.5",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz",
- "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==",
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.1.tgz",
+ "integrity": "sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==",
"cpu": [
"x64"
],
@@ -1664,10 +1040,108 @@
"url": "https://opencollective.com/libvips"
}
},
+ "node_modules/@internationalized/number": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.2.tgz",
+ "integrity": "sha512-E5QTOlMg9wo5OrKdHD6edo1JJlIoOsylh0+mbf0evi1tHJwMZfJSaBpGtnJV9N7w3jeiioox9EG/EWRWPh82vg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/fs-minipass": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
+ "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^7.0.4"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@isaacs/fs-minipass/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/set-array": "^1.2.1",
@@ -1678,20 +1152,11 @@
"node": ">=6.0.0"
}
},
- "node_modules/@jridgewell/gen-mapping/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.25",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
- "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
@@ -1701,6 +1166,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
@@ -1708,31 +1174,43 @@
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
- "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+ "dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jridgewell/resolve-uri": "^3.0.3",
- "@jridgewell/sourcemap-codec": "^1.4.10"
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@napi-rs/wasm-runtime": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.10.tgz",
+ "integrity": "sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.4.3",
+ "@emnapi/runtime": "^1.4.3",
+ "@tybys/wasm-util": "^0.9.0"
}
},
"node_modules/@next/env": {
- "version": "15.1.2",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.2.tgz",
- "integrity": "sha512-Hm3jIGsoUl6RLB1vzY+dZeqb+/kWPZ+h34yiWxW0dV87l8Im/eMOwpOA+a0L78U0HM04syEjXuRlCozqpwuojQ==",
+ "version": "15.3.2",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.2.tgz",
+ "integrity": "sha512-xURk++7P7qR9JG1jJtLzPzf0qEvqCN0A/T3DXf8IPMKo9/6FfjxtEffRJIIew/bIL4T3C2jLLqBor8B/zVlx6g==",
"license": "MIT"
},
"node_modules/@next/eslint-plugin-next": {
- "version": "15.1.2",
- "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.1.2.tgz",
- "integrity": "sha512-sgfw3+WdaYOGPKCvM1L+UucBmRfh8V2Ygefp7ELON0+0vY7uohQwXXnVWg3rY7mXDKharQR3o7uedpfvnU2hlQ==",
+ "version": "15.3.2",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.3.2.tgz",
+ "integrity": "sha512-ijVRTXBgnHT33aWnDtmlG+LJD+5vhc9AKTJPquGG5NKXjpKNjc62woIhFtrAcWdBobt8kqjCoaJ0q6sDQoX7aQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1740,9 +1218,9 @@
}
},
"node_modules/@next/swc-darwin-arm64": {
- "version": "15.1.2",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.2.tgz",
- "integrity": "sha512-b9TN7q+j5/7+rGLhFAVZiKJGIASuo8tWvInGfAd8wsULjB1uNGRCj1z1WZwwPWzVQbIKWFYqc+9L7W09qwt52w==",
+ "version": "15.3.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.2.tgz",
+ "integrity": "sha512-2DR6kY/OGcokbnCsjHpNeQblqCZ85/1j6njYSkzRdpLn5At7OkSdmk7WyAmB9G0k25+VgqVZ/u356OSoQZ3z0g==",
"cpu": [
"arm64"
],
@@ -1756,9 +1234,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
- "version": "15.1.2",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.2.tgz",
- "integrity": "sha512-caR62jNDUCU+qobStO6YJ05p9E+LR0EoXh1EEmyU69cYydsAy7drMcOlUlRtQihM6K6QfvNwJuLhsHcCzNpqtA==",
+ "version": "15.3.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.2.tgz",
+ "integrity": "sha512-ro/fdqaZWL6k1S/5CLv1I0DaZfDVJkWNaUU3un8Lg6m0YENWlDulmIWzV96Iou2wEYyEsZq51mwV8+XQXqMp3w==",
"cpu": [
"x64"
],
@@ -1772,9 +1250,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
- "version": "15.1.2",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.2.tgz",
- "integrity": "sha512-fHHXBusURjBmN6VBUtu6/5s7cCeEkuGAb/ZZiGHBLVBXMBy4D5QpM8P33Or8JD1nlOjm/ZT9sEE5HouQ0F+hUA==",
+ "version": "15.3.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.2.tgz",
+ "integrity": "sha512-covwwtZYhlbRWK2HlYX9835qXum4xYZ3E2Mra1mdQ+0ICGoMiw1+nVAn4d9Bo7R3JqSmK1grMq/va+0cdh7bJA==",
"cpu": [
"arm64"
],
@@ -1788,9 +1266,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
- "version": "15.1.2",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.2.tgz",
- "integrity": "sha512-9CF1Pnivij7+M3G74lxr+e9h6o2YNIe7QtExWq1KUK4hsOLTBv6FJikEwCaC3NeYTflzrm69E5UfwEAbV2U9/g==",
+ "version": "15.3.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.2.tgz",
+ "integrity": "sha512-KQkMEillvlW5Qk5mtGA/3Yz0/tzpNlSw6/3/ttsV1lNtMuOHcGii3zVeXZyi4EJmmLDKYcTcByV2wVsOhDt/zg==",
"cpu": [
"arm64"
],
@@ -1804,9 +1282,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
- "version": "15.1.2",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.2.tgz",
- "integrity": "sha512-tINV7WmcTUf4oM/eN3Yuu/f8jQ5C6AkueZPKeALs/qfdfX57eNv4Ij7rt0SA6iZ8+fMobVfcFVv664Op0caCCg==",
+ "version": "15.3.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.2.tgz",
+ "integrity": "sha512-uRBo6THWei0chz+Y5j37qzx+BtoDRFIkDzZjlpCItBRXyMPIg079eIkOCl3aqr2tkxL4HFyJ4GHDes7W8HuAUg==",
"cpu": [
"x64"
],
@@ -1820,9 +1298,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
- "version": "15.1.2",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.2.tgz",
- "integrity": "sha512-jf2IseC4WRsGkzeUw/cK3wci9pxR53GlLAt30+y+B+2qAQxMw6WAC3QrANIKxkcoPU3JFh/10uFfmoMDF9JXKg==",
+ "version": "15.3.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.2.tgz",
+ "integrity": "sha512-+uxFlPuCNx/T9PdMClOqeE8USKzj8tVz37KflT3Kdbx/LOlZBRI2yxuIcmx1mPNK8DwSOMNCr4ureSet7eyC0w==",
"cpu": [
"x64"
],
@@ -1836,9 +1314,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
- "version": "15.1.2",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.2.tgz",
- "integrity": "sha512-wvg7MlfnaociP7k8lxLX4s2iBJm4BrNiNFhVUY+Yur5yhAJHfkS8qPPeDEUH8rQiY0PX3u/P7Q/wcg6Mv6GSAA==",
+ "version": "15.3.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.2.tgz",
+ "integrity": "sha512-LLTKmaI5cfD8dVzh5Vt7+OMo+AIOClEdIU/TSKbXXT2iScUTSxOGoBhfuv+FU8R9MLmrkIL1e2fBMkEEjYAtPQ==",
"cpu": [
"arm64"
],
@@ -1852,9 +1330,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
- "version": "15.1.2",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.2.tgz",
- "integrity": "sha512-D3cNA8NoT3aWISWmo7HF5Eyko/0OdOO+VagkoJuiTk7pyX3P/b+n8XA/MYvyR+xSVcbKn68B1rY9fgqjNISqzQ==",
+ "version": "15.3.2",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.2.tgz",
+ "integrity": "sha512-aW5B8wOPioJ4mBdMDXkt5f3j8pUr9W8AnlX0Df35uRWNT1Y6RIybxjnSUe+PhM+M1bwgyY8PHLmXZC6zT1o5tA==",
"cpu": [
"x64"
],
@@ -1915,262 +1393,1054 @@
"node": ">=12.4.0"
}
},
- "node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.1.tgz",
- "integrity": "sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
+ "node_modules/@npmcli/fs": {
+ "version": "1.1.1",
+ "license": "ISC",
"optional": true,
- "os": [
- "android"
- ]
+ "dependencies": {
+ "@gar/promisify": "^1.0.1",
+ "semver": "^7.3.5"
+ }
},
- "node_modules/@rollup/rollup-android-arm64": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.1.tgz",
- "integrity": "sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
+ "node_modules/@npmcli/move-file": {
+ "version": "1.1.2",
"license": "MIT",
"optional": true,
- "os": [
- "android"
- ]
+ "dependencies": {
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
},
- "node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.1.tgz",
- "integrity": "sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
+ "node_modules/@npmcli/move-file/node_modules/rimraf": {
+ "version": "3.0.2",
+ "license": "ISC",
"optional": true,
- "os": [
- "darwin"
- ]
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
},
- "node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.1.tgz",
- "integrity": "sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"dev": true,
"license": "MIT",
"optional": true,
- "os": [
- "darwin"
- ]
+ "engines": {
+ "node": ">=14"
+ }
},
- "node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.1.tgz",
- "integrity": "sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
+ "node_modules/@radix-ui/number": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz",
+ "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==",
+ "license": "MIT"
},
- "node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.1.tgz",
- "integrity": "sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
+ "node_modules/@radix-ui/primitive": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.2.tgz",
+ "integrity": "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==",
+ "license": "MIT"
},
- "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.1.tgz",
- "integrity": "sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==",
- "cpu": [
- "arm"
- ],
- "dev": true,
+ "node_modules/@radix-ui/react-accordion": {
+ "version": "1.2.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.11.tgz",
+ "integrity": "sha512-l3W5D54emV2ues7jjeG1xcyN7S3jnK3zE2zHqgn0CmMsy9lNJwmgcrmaxS+7ipw15FAivzKNzH3d5EcGoFKw0A==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-collapsible": "1.1.11",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
},
- "node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.1.tgz",
- "integrity": "sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==",
- "cpu": [
- "arm"
- ],
- "dev": true,
+ "node_modules/@radix-ui/react-arrow": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
+ "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
},
- "node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.1.tgz",
- "integrity": "sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
+ "node_modules/@radix-ui/react-collapsible": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.11.tgz",
+ "integrity": "sha512-2qrRsVGSCYasSz1RFOorXwl0H7g7J1frQtgpQgYrt+MOidtPAINHn9CPovQXb83r8ahapdx3Tu0fa/pdFFSdPg==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-presence": "1.1.4",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
},
- "node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.1.tgz",
- "integrity": "sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
+ "node_modules/@radix-ui/react-collection": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
+ "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
},
- "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.1.tgz",
- "integrity": "sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
+ "node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
+ "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
},
- "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.1.tgz",
- "integrity": "sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
+ "node_modules/@radix-ui/react-context": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
},
- "node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.1.tgz",
- "integrity": "sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
+ "node_modules/@radix-ui/react-dialog": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.14.tgz",
+ "integrity": "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.10",
+ "@radix-ui/react-focus-guards": "1.1.2",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.4",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
},
- "node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.1.tgz",
- "integrity": "sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
+ "node_modules/@radix-ui/react-direction": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
+ "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
},
- "node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.1.tgz",
- "integrity": "sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
+ "node_modules/@radix-ui/react-dismissable-layer": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz",
+ "integrity": "sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-escape-keydown": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
},
- "node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz",
- "integrity": "sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
+ "node_modules/@radix-ui/react-dropdown-menu": {
+ "version": "2.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.15.tgz",
+ "integrity": "sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==",
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-menu": "2.1.15",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
},
- "node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.1.tgz",
- "integrity": "sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
+ "node_modules/@radix-ui/react-focus-guards": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz",
+ "integrity": "sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==",
"license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
},
- "node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.1.tgz",
- "integrity": "sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
+ "node_modules/@radix-ui/react-focus-scope": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
+ "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
"license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-id": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-menu": {
+ "version": "2.1.15",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.15.tgz",
+ "integrity": "sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.10",
+ "@radix-ui/react-focus-guards": "1.1.2",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.7",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.4",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.10",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popover": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.14.tgz",
+ "integrity": "sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.10",
+ "@radix-ui/react-focus-guards": "1.1.2",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.7",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.4",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-popper": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.7.tgz",
+ "integrity": "sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.0.0",
+ "@radix-ui/react-arrow": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-rect": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1",
+ "@radix-ui/rect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-portal": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
+ "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-presence": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.4.tgz",
+ "integrity": "sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-roving-focus": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.10.tgz",
+ "integrity": "sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-select": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.5.tgz",
+ "integrity": "sha512-HnMTdXEVuuyzx63ME0ut4+sEMYW6oouHWNGUZc7ddvUWIcfCva/AMoqEW/3wnEllriMWBa0RHspCYnfCWJQYmA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.1",
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-dismissable-layer": "1.1.10",
+ "@radix-ui/react-focus-guards": "1.1.2",
+ "@radix-ui/react-focus-scope": "1.1.7",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.7",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-callback-ref": "1.1.1",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-visually-hidden": "1.2.3",
+ "aria-hidden": "^1.2.4",
+ "react-remove-scroll": "^2.6.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-separator": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz",
+ "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slider": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.3.5.tgz",
+ "integrity": "sha512-rkfe2pU2NBAYfGaxa3Mqosi7VZEWX5CxKaanRv0vZd4Zhl9fvQrg0VM93dv3xGLGfrHuoTRF3JXH8nb9g+B3fw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/number": "1.1.1",
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-collection": "1.1.7",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slot": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-switch": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.5.tgz",
+ "integrity": "sha512-5ijLkak6ZMylXsaImpZ8u4Rlf5grRmoc0p0QeX9VJtlrM4f5m3nCTX8tWga/zOA8PZYIR/t0p2Mnvd7InrJ6yQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-use-previous": "1.1.1",
+ "@radix-ui/react-use-size": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tabs": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.12.tgz",
+ "integrity": "sha512-GTVAlRVrQrSw3cEARM0nAx73ixrWDPNZAruETn3oHCNP6SbZ/hNxdxp+u7VkIEv3/sFoLq1PfcHrl7Pnp0CDpw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-direction": "1.1.1",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-presence": "1.1.4",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-roving-focus": "1.1.10",
+ "@radix-ui/react-use-controllable-state": "1.2.2"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tooltip": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.7.tgz",
+ "integrity": "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.2",
+ "@radix-ui/react-compose-refs": "1.1.2",
+ "@radix-ui/react-context": "1.1.2",
+ "@radix-ui/react-dismissable-layer": "1.1.10",
+ "@radix-ui/react-id": "1.1.1",
+ "@radix-ui/react-popper": "1.2.7",
+ "@radix-ui/react-portal": "1.1.9",
+ "@radix-ui/react-presence": "1.1.4",
+ "@radix-ui/react-primitive": "2.1.3",
+ "@radix-ui/react-slot": "1.2.3",
+ "@radix-ui/react-use-controllable-state": "1.2.2",
+ "@radix-ui/react-visually-hidden": "1.2.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-callback-ref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-effect-event": "0.0.2",
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-effect-event": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
+ "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-escape-keydown": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
+ "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-callback-ref": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-previous": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
+ "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
+ "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/rect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-size": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
+ "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-visually-hidden": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
+ "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.1.3"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/rect": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
+ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
+ "license": "MIT"
+ },
+ "node_modules/@react-aria/focus": {
+ "version": "3.20.3",
+ "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.20.3.tgz",
+ "integrity": "sha512-rR5uZUMSY4xLHmpK/I8bP1V6vUNHFo33gTvrvNUsAKKqvMfa7R2nu5A6v97dr5g6tVH6xzpdkPsOJCWh90H2cw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-aria/interactions": "^3.25.1",
+ "@react-aria/utils": "^3.29.0",
+ "@react-types/shared": "^3.29.1",
+ "@swc/helpers": "^0.5.0",
+ "clsx": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-aria/interactions": {
+ "version": "3.25.1",
+ "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.25.1.tgz",
+ "integrity": "sha512-ntLrlgqkmZupbbjekz3fE/n3eQH2vhncx8gUp0+N+GttKWevx7jos11JUBjnJwb1RSOPgRUFcrluOqBp0VgcfQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-aria/ssr": "^3.9.8",
+ "@react-aria/utils": "^3.29.0",
+ "@react-stately/flags": "^3.1.1",
+ "@react-types/shared": "^3.29.1",
+ "@swc/helpers": "^0.5.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-aria/ssr": {
+ "version": "3.9.8",
+ "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.8.tgz",
+ "integrity": "sha512-lQDE/c9uTfBSDOjaZUJS8xP2jCKVk4zjQeIlCH90xaLhHDgbpCdns3xvFpJJujfj3nI4Ll9K7A+ONUBDCASOuw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ },
+ "engines": {
+ "node": ">= 12"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-aria/utils": {
+ "version": "3.29.0",
+ "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.29.0.tgz",
+ "integrity": "sha512-jSOrZimCuT1iKNVlhjIxDkAhgF7HSp3pqyT6qjg/ZoA0wfqCi/okmrMPiWSAKBnkgX93N8GYTLT3CIEO6WZe9Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@react-aria/ssr": "^3.9.8",
+ "@react-stately/flags": "^3.1.1",
+ "@react-stately/utils": "^3.10.6",
+ "@react-types/shared": "^3.29.1",
+ "@swc/helpers": "^0.5.0",
+ "clsx": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1",
+ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-stately/flags": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.1.tgz",
+ "integrity": "sha512-XPR5gi5LfrPdhxZzdIlJDz/B5cBf63l4q6/AzNqVWFKgd0QqY5LvWJftXkklaIUpKSJkIKQb8dphuZXDtkWNqg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ }
+ },
+ "node_modules/@react-stately/utils": {
+ "version": "3.10.6",
+ "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.6.tgz",
+ "integrity": "sha512-O76ip4InfTTzAJrg8OaZxKU4vvjMDOpfA/PGNOytiXwBbkct2ZeZwaimJ8Bt9W1bj5VsZ81/o/tW4BacbdDOMA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@swc/helpers": "^0.5.0"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
+ },
+ "node_modules/@react-types/shared": {
+ "version": "3.29.1",
+ "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.29.1.tgz",
+ "integrity": "sha512-KtM+cDf2CXoUX439rfEhbnEdAgFZX20UP2A35ypNIawR7/PFFPjQDWyA2EnClCcW/dLWJDEPX2U8+EJff8xqmQ==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
+ }
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.29.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.1.tgz",
- "integrity": "sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==",
"cpu": [
"x64"
],
@@ -2189,9 +2459,9 @@
"license": "MIT"
},
"node_modules/@rushstack/eslint-patch": {
- "version": "1.10.4",
- "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz",
- "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==",
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.11.0.tgz",
+ "integrity": "sha512-zxnHvoMQVqewTJr/W4pKjF0bMGiKJv1WX7bSrkl46Hg0QjESbzBROWK0Wg4RphzSOS5Jiy7eFimmM3UgMrMZbQ==",
"dev": true,
"license": "MIT"
},
@@ -2210,10 +2480,485 @@
"tslib": "^2.8.0"
}
},
+ "node_modules/@tailwindcss/forms": {
+ "version": "0.5.10",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.10.tgz",
+ "integrity": "sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw==",
+ "license": "MIT",
+ "dependencies": {
+ "mini-svg-data-uri": "^1.2.3"
+ },
+ "peerDependencies": {
+ "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1"
+ }
+ },
+ "node_modules/@tailwindcss/node": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.7.tgz",
+ "integrity": "sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.3.0",
+ "enhanced-resolve": "^5.18.1",
+ "jiti": "^2.4.2",
+ "lightningcss": "1.30.1",
+ "magic-string": "^0.30.17",
+ "source-map-js": "^1.2.1",
+ "tailwindcss": "4.1.7"
+ }
+ },
+ "node_modules/@tailwindcss/oxide": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.7.tgz",
+ "integrity": "sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^2.0.4",
+ "tar": "^7.4.3"
+ },
+ "engines": {
+ "node": ">= 10"
+ },
+ "optionalDependencies": {
+ "@tailwindcss/oxide-android-arm64": "4.1.7",
+ "@tailwindcss/oxide-darwin-arm64": "4.1.7",
+ "@tailwindcss/oxide-darwin-x64": "4.1.7",
+ "@tailwindcss/oxide-freebsd-x64": "4.1.7",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.7",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.1.7",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.1.7",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.1.7",
+ "@tailwindcss/oxide-linux-x64-musl": "4.1.7",
+ "@tailwindcss/oxide-wasm32-wasi": "4.1.7",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.1.7",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.1.7"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-android-arm64": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.7.tgz",
+ "integrity": "sha512-IWA410JZ8fF7kACus6BrUwY2Z1t1hm0+ZWNEzykKmMNM09wQooOcN/VXr0p/WJdtHZ90PvJf2AIBS/Ceqx1emg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-arm64": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.7.tgz",
+ "integrity": "sha512-81jUw9To7fimGGkuJ2W5h3/oGonTOZKZ8C2ghm/TTxbwvfSiFSDPd6/A/KE2N7Jp4mv3Ps9OFqg2fEKgZFfsvg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-x64": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.7.tgz",
+ "integrity": "sha512-q77rWjEyGHV4PdDBtrzO0tgBBPlQWKY7wZK0cUok/HaGgbNKecegNxCGikuPJn5wFAlIywC3v+WMBt0PEBtwGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-freebsd-x64": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.7.tgz",
+ "integrity": "sha512-RfmdbbK6G6ptgF4qqbzoxmH+PKfP4KSVs7SRlTwcbRgBwezJkAO3Qta/7gDy10Q2DcUVkKxFLXUQO6J3CRvBGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.7.tgz",
+ "integrity": "sha512-OZqsGvpwOa13lVd1z6JVwQXadEobmesxQ4AxhrwRiPuE04quvZHWn/LnihMg7/XkN+dTioXp/VMu/p6A5eZP3g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.7.tgz",
+ "integrity": "sha512-voMvBTnJSfKecJxGkoeAyW/2XRToLZ227LxswLAwKY7YslG/Xkw9/tJNH+3IVh5bdYzYE7DfiaPbRkSHFxY1xA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.7.tgz",
+ "integrity": "sha512-PjGuNNmJeKHnP58M7XyjJyla8LPo+RmwHQpBI+W/OxqrwojyuCQ+GUtygu7jUqTEexejZHr/z3nBc/gTiXBj4A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.7.tgz",
+ "integrity": "sha512-HMs+Va+ZR3gC3mLZE00gXxtBo3JoSQxtu9lobbZd+DmfkIxR54NO7Z+UQNPsa0P/ITn1TevtFxXTpsRU7qEvWg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.7.tgz",
+ "integrity": "sha512-MHZ6jyNlutdHH8rd+YTdr3QbXrHXqwIhHw9e7yXEBcQdluGwhpQY2Eku8UZK6ReLaWtQ4gijIv5QoM5eE+qlsA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.7.tgz",
+ "integrity": "sha512-ANaSKt74ZRzE2TvJmUcbFQ8zS201cIPxUDm5qez5rLEwWkie2SkGtA4P+GPTj+u8N6JbPrC8MtY8RmJA35Oo+A==",
+ "bundleDependencies": [
+ "@napi-rs/wasm-runtime",
+ "@emnapi/core",
+ "@emnapi/runtime",
+ "@tybys/wasm-util",
+ "@emnapi/wasi-threads",
+ "tslib"
+ ],
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.4.3",
+ "@emnapi/runtime": "^1.4.3",
+ "@emnapi/wasi-threads": "^1.0.2",
+ "@napi-rs/wasm-runtime": "^0.2.9",
+ "@tybys/wasm-util": "^0.9.0",
+ "tslib": "^2.8.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.7.tgz",
+ "integrity": "sha512-HUiSiXQ9gLJBAPCMVRk2RT1ZrBjto7WvqsPBwUrNK2BcdSxMnk19h4pjZjI7zgPhDxlAbJSumTC4ljeA9y0tEw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.7.tgz",
+ "integrity": "sha512-rYHGmvoHiLJ8hWucSfSOEmdCBIGZIq7SpkPRSqLsH2Ab2YUNgKeAPT1Fi2cx3+hnYOrAb0jp9cRyode3bBW4mQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tailwindcss/oxide/node_modules/chownr": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
+ "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@tailwindcss/oxide/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/@tailwindcss/oxide/node_modules/minizlib": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
+ "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@tailwindcss/oxide/node_modules/mkdirp": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
+ "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "dist/cjs/src/bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@tailwindcss/oxide/node_modules/tar": {
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
+ "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@isaacs/fs-minipass": "^4.0.0",
+ "chownr": "^3.0.0",
+ "minipass": "^7.1.2",
+ "minizlib": "^3.0.1",
+ "mkdirp": "^3.0.1",
+ "yallist": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@tailwindcss/oxide/node_modules/yallist": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
+ "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@tailwindcss/postcss": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.7.tgz",
+ "integrity": "sha512-88g3qmNZn7jDgrrcp3ZXEQfp9CVox7xjP1HN2TFKI03CltPVd/c61ydn5qJJL8FYunn0OqBaW5HNUga0kmPVvw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "@tailwindcss/node": "4.1.7",
+ "@tailwindcss/oxide": "4.1.7",
+ "postcss": "^8.4.41",
+ "tailwindcss": "4.1.7"
+ }
+ },
+ "node_modules/@tailwindcss/typography": {
+ "version": "0.5.16",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz",
+ "integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==",
+ "license": "MIT",
+ "dependencies": {
+ "lodash.castarray": "^4.4.0",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.merge": "^4.6.2",
+ "postcss-selector-parser": "6.0.10"
+ },
+ "peerDependencies": {
+ "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1"
+ }
+ },
+ "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": {
+ "version": "6.0.10",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
+ "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@tanstack/react-virtual": {
+ "version": "3.13.9",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.9.tgz",
+ "integrity": "sha512-SPWC8kwG/dWBf7Py7cfheAPOxuvIv4fFQ54PdmYbg7CpXfsKxkucak43Q0qKsxVthhUJQ1A7CIMAIplq4BjVwA==",
+ "license": "MIT",
+ "dependencies": {
+ "@tanstack/virtual-core": "3.13.9"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@tanstack/virtual-core": {
+ "version": "3.13.9",
+ "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.9.tgz",
+ "integrity": "sha512-3jztt0jpaoJO5TARe2WIHC1UQC3VMLAFUW5mmMo0yrkwtDB2AQP0+sh10BVUpWrnvHjSLvzFizydtEGLCJKFoQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tootallnate/once": {
+ "version": "1.1.2",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@tsconfig/node10": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
+ "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node12": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+ "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node14": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+ "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node16": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
+ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz",
+ "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/bcrypt": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.2.tgz",
+ "integrity": "sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/body-parser": {
"version": "1.19.5",
- "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
- "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2223,38 +2968,54 @@
},
"node_modules/@types/connect": {
"version": "3.4.38",
- "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
- "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
+ "node_modules/@types/debug": {
+ "version": "4.1.12",
+ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
+ "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/ms": "*"
+ }
+ },
"node_modules/@types/estree": {
"version": "1.0.6",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
- "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
- "dev": true,
"license": "MIT"
},
+ "node_modules/@types/estree-jsx": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz",
+ "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "*"
+ }
+ },
"node_modules/@types/express": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz",
- "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==",
+ "version": "5.0.1",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^5.0.0",
- "@types/qs": "*",
"@types/serve-static": "*"
}
},
+ "node_modules/@types/express-rate-limit": {
+ "version": "5.1.3",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/express": "*"
+ }
+ },
"node_modules/@types/express-serve-static-core": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz",
- "integrity": "sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg==",
+ "version": "5.0.6",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2264,10 +3025,17 @@
"@types/send": "*"
}
},
+ "node_modules/@types/hast": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
+ "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
"node_modules/@types/http-errors": {
"version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
- "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==",
"dev": true,
"license": "MIT"
},
@@ -2285,99 +3053,127 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/mdast": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
+ "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
"node_modules/@types/mime": {
"version": "1.3.5",
- "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
- "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
"dev": true,
"license": "MIT"
},
- "node_modules/@types/minimist": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
- "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==",
- "dev": true,
+ "node_modules/@types/ms": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
+ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
"license": "MIT"
},
"node_modules/@types/node": {
"version": "20.17.10",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.10.tgz",
- "integrity": "sha512-/jrvh5h6NXhEauFFexRin69nA0uHJ5gwk4iDivp/DeoEua3uwCUto6PC86IpRITBOs4+6i2I56K5x5b6WYGXHA==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.19.2"
}
},
- "node_modules/@types/node-forge": {
- "version": "1.3.11",
- "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz",
- "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==",
+ "node_modules/@types/pg": {
+ "version": "8.15.2",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/node": "*"
+ "@types/node": "*",
+ "pg-protocol": "*",
+ "pg-types": "^4.0.1"
}
},
- "node_modules/@types/normalize-package-data": {
- "version": "2.4.4",
- "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
- "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/parse-json": {
+ "node_modules/@types/pg/node_modules/pg-types": {
"version": "4.0.2",
- "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
- "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==",
- "license": "MIT"
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pg-int8": "1.0.1",
+ "pg-numeric": "1.0.2",
+ "postgres-array": "~3.0.1",
+ "postgres-bytea": "~3.0.0",
+ "postgres-date": "~2.1.0",
+ "postgres-interval": "^3.0.0",
+ "postgres-range": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@types/pg/node_modules/postgres-array": {
+ "version": "3.0.4",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@types/pg/node_modules/postgres-bytea": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "obuf": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@types/pg/node_modules/postgres-date": {
+ "version": "2.1.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@types/pg/node_modules/postgres-interval": {
+ "version": "3.0.0",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
},
"node_modules/@types/qs": {
- "version": "6.9.17",
- "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz",
- "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==",
+ "version": "6.9.18",
"dev": true,
"license": "MIT"
},
"node_modules/@types/range-parser": {
"version": "1.2.7",
- "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
- "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/react": {
- "version": "19.0.2",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.2.tgz",
- "integrity": "sha512-USU8ZI/xyKJwFTpjSVIrSeHBVAGagkHQKPNbxeWwql/vDmnTIBgx+TJnhFnj1NXgz8XfprU0egV2dROLGpsBEg==",
+ "version": "19.1.4",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.4.tgz",
+ "integrity": "sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==",
"license": "MIT",
"dependencies": {
"csstype": "^3.0.2"
}
},
"node_modules/@types/react-dom": {
- "version": "19.0.2",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.2.tgz",
- "integrity": "sha512-c1s+7TKFaDRRxr1TxccIX2u7sfCnc3RxkVyBIUA2lCpyqCF+QoAwQ/CBg7bsMdVwP120HEH143VQezKtef5nCg==",
- "dev": true,
+ "version": "19.1.5",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.5.tgz",
+ "integrity": "sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg==",
+ "devOptional": true,
"license": "MIT",
"peerDependencies": {
"@types/react": "^19.0.0"
}
},
- "node_modules/@types/react-transition-group": {
- "version": "4.4.12",
- "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
- "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*"
- }
- },
"node_modules/@types/send": {
"version": "0.17.4",
- "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
- "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2387,8 +3183,6 @@
},
"node_modules/@types/serve-static": {
"version": "1.15.7",
- "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz",
- "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2397,55 +3191,32 @@
"@types/send": "*"
}
},
- "node_modules/@types/ssh2": {
- "version": "1.15.1",
- "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.15.1.tgz",
- "integrity": "sha512-ZIbEqKAsi5gj35y4P4vkJYly642wIbY6PqoN0xiyQGshKUGXR9WQjF/iF9mXBQ8uBKy3ezfsCkcoHKhd0BzuDA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "^18.11.18"
- }
- },
- "node_modules/@types/ssh2/node_modules/@types/node": {
- "version": "18.19.68",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz",
- "integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "undici-types": "~5.26.4"
- }
- },
- "node_modules/@types/ssh2/node_modules/undici-types": {
- "version": "5.26.5",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
- "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/triple-beam": {
"version": "1.3.5",
- "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
- "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.18.2",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.2.tgz",
- "integrity": "sha512-adig4SzPLjeQ0Tm+jvsozSGiCliI2ajeURDGHjZ2llnA+A67HihCQ+a3amtPhUakd1GlwHxSRvzOZktbEvhPPg==",
+ "version": "8.32.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz",
+ "integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.18.2",
- "@typescript-eslint/type-utils": "8.18.2",
- "@typescript-eslint/utils": "8.18.2",
- "@typescript-eslint/visitor-keys": "8.18.2",
+ "@typescript-eslint/scope-manager": "8.32.1",
+ "@typescript-eslint/type-utils": "8.32.1",
+ "@typescript-eslint/utils": "8.32.1",
+ "@typescript-eslint/visitor-keys": "8.32.1",
"graphemer": "^1.4.0",
- "ignore": "^5.3.1",
+ "ignore": "^7.0.0",
"natural-compare": "^1.4.0",
- "ts-api-utils": "^1.3.0"
+ "ts-api-utils": "^2.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2457,20 +3228,30 @@
"peerDependencies": {
"@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.8.0"
+ "typescript": ">=4.8.4 <5.9.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz",
+ "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.18.2",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.2.tgz",
- "integrity": "sha512-y7tcq4StgxQD4mDr9+Jb26dZ+HTZ/SkfqpXSiqeUXZHxOUyjWDKsmwKhJ0/tApR08DgOhrFAoAhyB80/p3ViuA==",
+ "version": "8.32.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz",
+ "integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.18.2",
- "@typescript-eslint/types": "8.18.2",
- "@typescript-eslint/typescript-estree": "8.18.2",
- "@typescript-eslint/visitor-keys": "8.18.2",
+ "@typescript-eslint/scope-manager": "8.32.1",
+ "@typescript-eslint/types": "8.32.1",
+ "@typescript-eslint/typescript-estree": "8.32.1",
+ "@typescript-eslint/visitor-keys": "8.32.1",
"debug": "^4.3.4"
},
"engines": {
@@ -2482,18 +3263,18 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.8.0"
+ "typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.18.2",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.2.tgz",
- "integrity": "sha512-YJFSfbd0CJjy14r/EvWapYgV4R5CHzptssoag2M7y3Ra7XNta6GPAJPPP5KGB9j14viYXyrzRO5GkX7CRfo8/g==",
+ "version": "8.32.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz",
+ "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.18.2",
- "@typescript-eslint/visitor-keys": "8.18.2"
+ "@typescript-eslint/types": "8.32.1",
+ "@typescript-eslint/visitor-keys": "8.32.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2504,16 +3285,16 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.18.2",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.2.tgz",
- "integrity": "sha512-AB/Wr1Lz31bzHfGm/jgbFR0VB0SML/hd2P1yxzKDM48YmP7vbyJNHRExUE/wZsQj2wUCvbWH8poNHFuxLqCTnA==",
+ "version": "8.32.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz",
+ "integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/typescript-estree": "8.18.2",
- "@typescript-eslint/utils": "8.18.2",
+ "@typescript-eslint/typescript-estree": "8.32.1",
+ "@typescript-eslint/utils": "8.32.1",
"debug": "^4.3.4",
- "ts-api-utils": "^1.3.0"
+ "ts-api-utils": "^2.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2524,13 +3305,13 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.8.0"
+ "typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.18.2",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.2.tgz",
- "integrity": "sha512-Z/zblEPp8cIvmEn6+tPDIHUbRu/0z5lqZ+NvolL5SvXWT5rQy7+Nch83M0++XzO0XrWRFWECgOAyE8bsJTl1GQ==",
+ "version": "8.32.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz",
+ "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2542,20 +3323,20 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.18.2",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.2.tgz",
- "integrity": "sha512-WXAVt595HjpmlfH4crSdM/1bcsqh+1weFRWIa9XMTx/XHZ9TCKMcr725tLYqWOgzKdeDrqVHxFotrvWcEsk2Tg==",
+ "version": "8.32.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz",
+ "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.18.2",
- "@typescript-eslint/visitor-keys": "8.18.2",
+ "@typescript-eslint/types": "8.32.1",
+ "@typescript-eslint/visitor-keys": "8.32.1",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
- "ts-api-utils": "^1.3.0"
+ "ts-api-utils": "^2.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2565,7 +3346,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "typescript": ">=4.8.4 <5.8.0"
+ "typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
@@ -2579,9 +3360,9 @@
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
- "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2589,7 +3370,7 @@
"@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.2",
"merge2": "^1.3.0",
- "micromatch": "^4.0.4"
+ "micromatch": "^4.0.8"
},
"engines": {
"node": ">=8.6.0"
@@ -2624,30 +3405,17 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/@typescript-eslint/utils": {
- "version": "8.18.2",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.2.tgz",
- "integrity": "sha512-Cr4A0H7DtVIPkauj4sTSXVl+VBWewE9/o40KcF3TV9aqDEOWoXF3/+oRXNby3DYzZeCATvbdksYsGZzplwnK/Q==",
+ "version": "8.32.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz",
+ "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@eslint-community/eslint-utils": "^4.4.0",
- "@typescript-eslint/scope-manager": "8.18.2",
- "@typescript-eslint/types": "8.18.2",
- "@typescript-eslint/typescript-estree": "8.18.2"
+ "@eslint-community/eslint-utils": "^4.7.0",
+ "@typescript-eslint/scope-manager": "8.32.1",
+ "@typescript-eslint/types": "8.32.1",
+ "@typescript-eslint/typescript-estree": "8.32.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2658,17 +3426,17 @@
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <5.8.0"
+ "typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.18.2",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.2.tgz",
- "integrity": "sha512-zORcwn4C3trOWiCqFQP1x6G3xTRyZ1LYydnj51cRnJ6hxBlr/cKPckk+PKPUw/fXmvfKTcw7bwY3w9izgx5jZw==",
+ "version": "8.32.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz",
+ "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.18.2",
+ "@typescript-eslint/types": "8.32.1",
"eslint-visitor-keys": "^4.2.0"
},
"engines": {
@@ -2679,10 +3447,255 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
+ "license": "ISC"
+ },
+ "node_modules/@unrs/resolver-binding-darwin-arm64": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.7.2.tgz",
+ "integrity": "sha512-vxtBno4xvowwNmO/ASL0Y45TpHqmNkAaDtz4Jqb+clmcVSSl8XCG/PNFFkGsXXXS6AMjP+ja/TtNCFFa1QwLRg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-x64": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.7.2.tgz",
+ "integrity": "sha512-qhVa8ozu92C23Hsmv0BF4+5Dyyd5STT1FolV4whNgbY6mj3kA0qsrGPe35zNR3wAN7eFict3s4Rc2dDTPBTuFQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-freebsd-x64": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.7.2.tgz",
+ "integrity": "sha512-zKKdm2uMXqLFX6Ac7K5ElnnG5VIXbDlFWzg4WJ8CGUedJryM5A3cTgHuGMw1+P5ziV8CRhnSEgOnurTI4vpHpg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.7.2.tgz",
+ "integrity": "sha512-8N1z1TbPnHH+iDS/42GJ0bMPLiGK+cUqOhNbMKtWJ4oFGzqSJk/zoXFzcQkgtI63qMcUI7wW1tq2usZQSb2jxw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.7.2.tgz",
+ "integrity": "sha512-tjYzI9LcAXR9MYd9rO45m1s0B/6bJNuZ6jeOxo1pq1K6OBuRMMmfyvJYval3s9FPPGmrldYA3mi4gWDlWuTFGA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.7.2.tgz",
+ "integrity": "sha512-jon9M7DKRLGZ9VYSkFMflvNqu9hDtOCEnO2QAryFWgT6o6AXU8du56V7YqnaLKr6rAbZBWYsYpikF226v423QA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.7.2.tgz",
+ "integrity": "sha512-c8Cg4/h+kQ63pL43wBNaVMmOjXI/X62wQmru51qjfTvI7kmCy5uHTJvK/9LrF0G8Jdx8r34d019P1DVJmhXQpA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.7.2.tgz",
+ "integrity": "sha512-A+lcwRFyrjeJmv3JJvhz5NbcCkLQL6Mk16kHTNm6/aGNc4FwPHPE4DR9DwuCvCnVHvF5IAd9U4VIs/VvVir5lg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.7.2.tgz",
+ "integrity": "sha512-hQQ4TJQrSQW8JlPm7tRpXN8OCNP9ez7PajJNjRD1ZTHQAy685OYqPrKjfaMw/8LiHCt8AZ74rfUVHP9vn0N69Q==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.7.2.tgz",
+ "integrity": "sha512-NoAGbiqrxtY8kVooZ24i70CjLDlUFI7nDj3I9y54U94p+3kPxwd2L692YsdLa+cqQ0VoqMWoehDFp21PKRUoIQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.7.2.tgz",
+ "integrity": "sha512-KaZByo8xuQZbUhhreBTW+yUnOIHUsv04P8lKjQ5otiGoSJ17ISGYArc+4vKdLEpGaLbemGzr4ZeUbYQQsLWFjA==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.7.2.tgz",
+ "integrity": "sha512-dEidzJDubxxhUCBJ/SHSMJD/9q7JkyfBMT77Px1npl4xpg9t0POLvnWywSk66BgZS/b2Hy9Y1yFaoMTFJUe9yg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-musl": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.7.2.tgz",
+ "integrity": "sha512-RvP+Ux3wDjmnZDT4XWFfNBRVG0fMsc+yVzNFUqOflnDfZ9OYujv6nkh+GOr+watwrW4wdp6ASfG/e7bkDradsw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-wasm32-wasi": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.7.2.tgz",
+ "integrity": "sha512-y797JBmO9IsvXVRCKDXOxjyAE4+CcZpla2GSoBQ33TVb3ILXuFnMrbR/QQZoauBYeOFuu4w3ifWLw52sdHGz6g==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@napi-rs/wasm-runtime": "^0.2.9"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.7.2.tgz",
+ "integrity": "sha512-gtYTh4/VREVSLA+gHrfbWxaMO/00y+34htY7XpioBTy56YN2eBjkPrY1ML1Zys89X3RJDKVaogzwxlM1qU7egg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.7.2.tgz",
+ "integrity": "sha512-Ywv20XHvHTDRQs12jd3MY8X5C8KLjDbg/jyaal/QLKx3fAShhJyD4blEANInsjxW3P7isHx1Blt56iUDDJO3jg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.7.2.tgz",
+ "integrity": "sha512-friS8NEQfHaDbkThxopGk+LuE5v3iY0StruifjQEt7SLbA46OnfgMO15sOTkbpJkol6RB+1l1TYPXh0sCddpvA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
"node_modules/@vitest/expect": {
"version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.8.tgz",
- "integrity": "sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2697,8 +3710,6 @@
},
"node_modules/@vitest/mocker": {
"version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.8.tgz",
- "integrity": "sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2724,8 +3735,6 @@
},
"node_modules/@vitest/pretty-format": {
"version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.8.tgz",
- "integrity": "sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2737,8 +3746,6 @@
},
"node_modules/@vitest/runner": {
"version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.8.tgz",
- "integrity": "sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2751,8 +3758,6 @@
},
"node_modules/@vitest/snapshot": {
"version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.8.tgz",
- "integrity": "sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2766,8 +3771,6 @@
},
"node_modules/@vitest/spy": {
"version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.8.tgz",
- "integrity": "sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2779,8 +3782,6 @@
},
"node_modules/@vitest/utils": {
"version": "2.1.8",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.8.tgz",
- "integrity": "sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2792,10 +3793,92 @@
"url": "https://opencollective.com/vitest"
}
},
+ "node_modules/@zag-js/anatomy": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/anatomy/-/anatomy-1.13.1.tgz",
+ "integrity": "sha512-o0syzwTVPei8g3Puy7NVhviVcB2KLvhYHpT19r3OMt4WtK4i9Qxy5V/7H6RFAf4Z5+xOYXfllJk9qtu3L3cwSg==",
+ "license": "MIT"
+ },
+ "node_modules/@zag-js/core": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/core/-/core-1.13.1.tgz",
+ "integrity": "sha512-8sDA9c2K5JMMLN7F7d4HUmeKxF+bpc7bB5DGkagevLZ+iomDdpg2B0sDDV88guq5/lYNfMJ6krSfO80JMO3Gjg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/dom-query": "1.13.1",
+ "@zag-js/utils": "1.13.1"
+ }
+ },
+ "node_modules/@zag-js/dom-query": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.13.1.tgz",
+ "integrity": "sha512-BWQB77N7dbbUauYGmG2YmL5eNCot9v/kuCVzeR3WHueApum7f14ZvbFM8Lr9+tCL4BibPyAc8mZzAiB1reHWWQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/types": "1.13.1"
+ }
+ },
+ "node_modules/@zag-js/number-input": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/number-input/-/number-input-1.13.1.tgz",
+ "integrity": "sha512-4HSSWUiUM876K16+eaHsIVeuu1TErAE3B4RrXX3fTHoqduM5EQTYtIXEuWzgvTscl9L8pmF9v9uSHpezHPoNPA==",
+ "license": "MIT",
+ "dependencies": {
+ "@internationalized/number": "3.6.2",
+ "@zag-js/anatomy": "1.13.1",
+ "@zag-js/core": "1.13.1",
+ "@zag-js/dom-query": "1.13.1",
+ "@zag-js/types": "1.13.1",
+ "@zag-js/utils": "1.13.1"
+ }
+ },
+ "node_modules/@zag-js/react": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/react/-/react-1.13.1.tgz",
+ "integrity": "sha512-UBzy9bnZBdDNaWppsn8W5vao9fLm8OMCo3Erf+3gf2Z/dHdD8bHd9ObNOxXLUYJhELBSDJvoJiSMNmX8N8RLVg==",
+ "license": "MIT",
+ "dependencies": {
+ "@zag-js/core": "1.13.1",
+ "@zag-js/store": "1.13.1",
+ "@zag-js/types": "1.13.1",
+ "@zag-js/utils": "1.13.1"
+ },
+ "peerDependencies": {
+ "react": ">=18.0.0",
+ "react-dom": ">=18.0.0"
+ }
+ },
+ "node_modules/@zag-js/store": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/store/-/store-1.13.1.tgz",
+ "integrity": "sha512-v5Y1S+7EB3pH5NgLKd1DN4w04SGGgYFUzRsBJD3jQuF/kuMqSYAEOfBM/cezAmphsAZRE2H7JmvhtZUSB7pzrw==",
+ "license": "MIT",
+ "dependencies": {
+ "proxy-compare": "3.0.1"
+ }
+ },
+ "node_modules/@zag-js/types": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/types/-/types-1.13.1.tgz",
+ "integrity": "sha512-i74ng4uyEFLKxw3JWxDtt2fFpJ0HkSuSHQQ+k+ZpHuErDbAA7r9BKtSqLne3Hw/gvjel4yU/uH88Ogdl1J55zg==",
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "3.1.3"
+ }
+ },
+ "node_modules/@zag-js/utils": {
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/@zag-js/utils/-/utils-1.13.1.tgz",
+ "integrity": "sha512-2nnBUxlf8eUv9khFBR6gbMogy1+/CSlIVYJrirN/w+v5r516QUXgzjlM6ZNSYGiF5kPgbxOUdgsNgTnvjyNvmA==",
+ "license": "MIT"
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "license": "ISC",
+ "optional": true
+ },
"node_modules/accepts": {
"version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
"license": "MIT",
"dependencies": {
"mime-types": "~2.1.34",
@@ -2806,9 +3889,9 @@
}
},
"node_modules/acorn": {
- "version": "8.14.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
- "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
+ "version": "8.14.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
+ "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"dev": true,
"license": "MIT",
"bin": {
@@ -2841,23 +3924,39 @@
"node": ">=0.4.0"
}
},
- "node_modules/add-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz",
- "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/agent-base": {
"version": "7.1.3",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
- "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">= 14"
}
},
+ "node_modules/agentkeepalive": {
+ "version": "4.6.0",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "humanize-ms": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -2877,9 +3976,7 @@
},
"node_modules/ansi-regex": {
"version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -2901,6 +3998,51 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/aproba": {
+ "version": "2.0.0",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/are-we-there-yet": {
+ "version": "3.0.1",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/arg": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -2908,6 +4050,18 @@
"dev": true,
"license": "Python-2.0"
},
+ "node_modules/aria-hidden": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
+ "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/aria-query": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
@@ -2937,15 +4091,6 @@
},
"node_modules/array-flatten": {
"version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
- "license": "MIT"
- },
- "node_modules/array-ify": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz",
- "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==",
- "dev": true,
"license": "MIT"
},
"node_modules/array-includes": {
@@ -2991,18 +4136,19 @@
}
},
"node_modules/array.prototype.findlastindex": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz",
- "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==",
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz",
+ "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
"define-properties": "^1.2.1",
- "es-abstract": "^1.23.2",
+ "es-abstract": "^1.23.9",
"es-errors": "^1.3.0",
- "es-object-atoms": "^1.0.0",
- "es-shim-unscopables": "^1.0.2"
+ "es-object-atoms": "^1.1.1",
+ "es-shim-unscopables": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
@@ -3088,40 +4234,8 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/arrify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
- "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/as-table": {
- "version": "1.0.55",
- "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz",
- "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "printable-characters": "^1.0.42"
- }
- },
- "node_modules/asn1": {
- "version": "0.2.6",
- "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
- "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "safer-buffer": "~2.1.0"
- }
- },
"node_modules/assertion-error": {
"version": "2.0.1",
- "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
- "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3137,26 +4251,62 @@
},
"node_modules/async": {
"version": "3.2.6",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
- "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
"license": "MIT"
},
- "node_modules/async-file": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/async-file/-/async-file-2.0.2.tgz",
- "integrity": "sha512-oVmpzk0eaqZ022vPnkYHS/GaZO0y1B2DwB6rInNYg/1Rc+2hs0oUushzYFkizUyDpBY0PbEJ/RoCkJyAbrNluw==",
+ "node_modules/async-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
+ "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "rimraf": "^2.5.2"
+ "engines": {
+ "node": ">= 0.4"
}
},
"node_modules/asynckit": {
"version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "optional": true,
+ "peer": true
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.21",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
+ "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.24.4",
+ "caniuse-lite": "^1.0.30001702",
+ "fraction.js": "^4.3.7",
+ "normalize-range": "^0.1.2",
+ "picocolors": "^1.1.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
},
"node_modules/available-typed-arrays": {
"version": "1.0.7",
@@ -3175,9 +4325,9 @@
}
},
"node_modules/axe-core": {
- "version": "4.10.2",
- "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz",
- "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==",
+ "version": "4.10.3",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz",
+ "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==",
"dev": true,
"license": "MPL-2.0",
"engines": {
@@ -3194,65 +4344,93 @@
"node": ">= 0.4"
}
},
- "node_modules/babel-plugin-macros": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
- "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
+ "node_modules/bail": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
+ "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
"license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.12.5",
- "cosmiconfig": "^7.0.0",
- "resolve": "^1.19.0"
- },
- "engines": {
- "node": ">=10",
- "npm": ">=6"
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
- "node_modules/bcrypt-pbkdf": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
- "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "tweetnacl": "^0.14.3"
- }
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
},
- "node_modules/beamup-cli": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/beamup-cli/-/beamup-cli-1.3.0.tgz",
- "integrity": "sha512-OjYg5FnrytUwoD2rNWpqs8166VFqlGas2FbwKOitaq42SdURwpoFMMjcajcC/goDJSStjDjH7b5Ey+e4jRa1tw==",
- "dev": true,
+ "node_modules/bcrypt": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
+ "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==",
+ "hasInstallScript": true,
"license": "MIT",
"dependencies": {
- "async-file": "2.0.2",
- "commander": "6.1.0",
- "crypto-js": "4.0.0",
- "node-ssh": "13.1.0"
+ "node-addon-api": "^8.3.0",
+ "node-gyp-build": "^4.8.4"
},
- "bin": {
- "beamup": "bin/index.js"
+ "engines": {
+ "node": ">= 18"
}
},
- "node_modules/blake3-wasm": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz",
- "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==",
+ "node_modules/bcrypt/node_modules/node-addon-api": {
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.1.tgz",
+ "integrity": "sha512-lytcDEdxKjGJPTLEfW4mYMigRezMlyJY8W4wxJK8zE533Jlb8L8dRuObJFWg2P+AuOIxoCgKF+2Oq4d4Zd0OUA==",
+ "license": "MIT",
+ "engines": {
+ "node": "^18 || ^20 || >= 21"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/bindings": {
+ "version": "1.5.0",
+ "license": "MIT",
+ "dependencies": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
},
"node_modules/body-parser": {
"version": "1.20.3",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
- "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
@@ -3275,8 +4453,6 @@
},
"node_modules/body-parser/node_modules/debug": {
"version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
@@ -3284,15 +4460,11 @@
},
"node_modules/body-parser/node_modules/ms": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/brace-expansion": {
"version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
@@ -3312,21 +4484,59 @@
"node": ">=8"
}
},
- "node_modules/buffer-from": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "node_modules/browserslist": {
+ "version": "4.24.5",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz",
+ "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==",
"dev": true,
- "license": "MIT"
- },
- "node_modules/buildcheck": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz",
- "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==",
- "dev": true,
- "optional": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001716",
+ "electron-to-chromium": "^1.5.149",
+ "node-releases": "^2.0.19",
+ "update-browserslist-db": "^1.1.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
"engines": {
- "node": ">=10.0.0"
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
}
},
"node_modules/busboy": {
@@ -3342,8 +4552,6 @@
},
"node_modules/bytes": {
"version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
@@ -3351,14 +4559,54 @@
},
"node_modules/cac": {
"version": "6.7.14",
- "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
- "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
+ "node_modules/cacache": {
+ "version": "15.3.0",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "@npmcli/fs": "^1.0.0",
+ "@npmcli/move-file": "^1.0.1",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "glob": "^7.1.4",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^6.0.0",
+ "minipass": "^3.1.1",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.2",
+ "mkdirp": "^1.0.3",
+ "p-map": "^4.0.0",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^8.0.1",
+ "tar": "^6.0.2",
+ "unique-filename": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/cacache/node_modules/rimraf": {
+ "version": "3.0.2",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/call-bind": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
@@ -3379,9 +4627,9 @@
}
},
"node_modules/call-bind-apply-helpers": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
- "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -3392,13 +4640,13 @@
}
},
"node_modules/call-bound": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
- "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "get-intrinsic": "^1.2.6"
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
@@ -3411,43 +4659,26 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
- "node_modules/camelcase-keys": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
- "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==",
+ "node_modules/camelcase-css": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "camelcase": "^5.3.1",
- "map-obj": "^4.0.0",
- "quick-lru": "^4.0.1"
- },
"engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">= 6"
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001690",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz",
- "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==",
+ "version": "1.0.30001718",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz",
+ "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==",
"funding": [
{
"type": "opencollective",
@@ -3464,21 +4695,18 @@
],
"license": "CC-BY-4.0"
},
- "node_modules/capnp-ts": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/capnp-ts/-/capnp-ts-0.7.0.tgz",
- "integrity": "sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==",
- "dev": true,
+ "node_modules/ccount": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
+ "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
"license": "MIT",
- "dependencies": {
- "debug": "^4.3.1",
- "tslib": "^2.2.0"
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/chai": {
"version": "5.1.2",
- "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz",
- "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3509,10 +4737,48 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
+ "node_modules/character-entities": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
+ "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-html4": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
+ "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
+ "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-reference-invalid": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
+ "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/check-error": {
"version": "2.1.1",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
- "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3520,19 +4786,68 @@
}
},
"node_modules/chokidar": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
- "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "readdirp": "^4.0.1"
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
},
"engines": {
- "node": ">= 14.16.0"
+ "node": ">= 8.10.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "2.0.0",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/class-variance-authority": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
+ "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "clsx": "^2.1.1"
+ },
+ "funding": {
+ "url": "https://polar.sh/cva"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=6"
}
},
"node_modules/client-only": {
@@ -3541,21 +4856,6 @@
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
"license": "MIT"
},
- "node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
@@ -3565,6 +4865,22 @@
"node": ">=6"
}
},
+ "node_modules/cmdk": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz",
+ "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "^1.1.1",
+ "@radix-ui/react-dialog": "^1.1.6",
+ "@radix-ui/react-id": "^1.1.0",
+ "@radix-ui/react-primitive": "^2.0.2"
+ },
+ "peerDependencies": {
+ "react": "^18 || ^19 || ^19.0.0-rc",
+ "react-dom": "^18 || ^19 || ^19.0.0-rc"
+ }
+ },
"node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
@@ -3594,24 +4910,26 @@
},
"node_modules/color-name": {
"version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"license": "MIT"
},
"node_modules/color-string": {
"version": "1.9.1",
- "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
- "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"license": "MIT",
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
+ "node_modules/color-support": {
+ "version": "1.1.3",
+ "license": "ISC",
+ "optional": true,
+ "bin": {
+ "color-support": "bin.js"
+ }
+ },
"node_modules/colorspace": {
"version": "1.1.4",
- "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
- "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
"license": "MIT",
"dependencies": {
"color": "^3.1.3",
@@ -3620,8 +4938,6 @@
},
"node_modules/colorspace/node_modules/color": {
"version": "3.2.1",
- "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
- "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
"license": "MIT",
"dependencies": {
"color-convert": "^1.9.3",
@@ -3630,8 +4946,6 @@
},
"node_modules/colorspace/node_modules/color-convert": {
"version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"license": "MIT",
"dependencies": {
"color-name": "1.1.3"
@@ -3639,16 +4953,14 @@
},
"node_modules/colorspace/node_modules/color-name": {
"version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
"license": "MIT"
},
"node_modules/combined-stream": {
"version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"delayed-stream": "~1.0.0"
},
@@ -3656,196 +4968,38 @@
"node": ">= 0.8"
}
},
+ "node_modules/comma-separated-tokens": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
+ "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/commander": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-6.1.0.tgz",
- "integrity": "sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
- "node_modules/commit-and-tag-version": {
- "version": "12.5.0",
- "resolved": "https://registry.npmjs.org/commit-and-tag-version/-/commit-and-tag-version-12.5.0.tgz",
- "integrity": "sha512-Ll7rkKntH20iEFOPUT4e503Jf3J0J8jSN+aSeHuvNdtv4xmv9kSLSBg2CWsMVihwF3J2WvMHBEUSCKuDNesiTA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "chalk": "^2.4.2",
- "conventional-changelog": "4.0.0",
- "conventional-changelog-config-spec": "2.1.0",
- "conventional-changelog-conventionalcommits": "6.1.0",
- "conventional-recommended-bump": "7.0.1",
- "detect-indent": "^6.0.0",
- "detect-newline": "^3.1.0",
- "dotgitignore": "^2.1.0",
- "figures": "^3.1.0",
- "find-up": "^5.0.0",
- "git-semver-tags": "^5.0.0",
- "jsdom": "^25.0.0",
- "semver": "^7.6.3",
- "w3c-xmlserializer": "^5.0.0",
- "yaml": "^2.4.1",
- "yargs": "^17.7.2"
- },
- "bin": {
- "commit-and-tag-version": "bin/cli.js"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/commit-and-tag-version/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/commit-and-tag-version/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/commit-and-tag-version/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/commit-and-tag-version/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/commit-and-tag-version/node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/commit-and-tag-version/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/commit-and-tag-version/node_modules/semver": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
- "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/commit-and-tag-version/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/commit-and-tag-version/node_modules/yaml": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz",
- "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "yaml": "bin.mjs"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/compare-func": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz",
- "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "array-ify": "^1.0.0",
- "dot-prop": "^5.1.0"
- }
- },
"node_modules/concat-map": {
"version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true,
+ "devOptional": true,
"license": "MIT"
},
- "node_modules/concat-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
- "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
- "dev": true,
- "engines": [
- "node >= 6.0"
- ],
- "license": "MIT",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.0.2",
- "typedarray": "^0.0.6"
- }
- },
- "node_modules/confbox": {
- "version": "0.1.8",
- "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
- "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
- "dev": true,
- "license": "MIT"
+ "node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "license": "ISC",
+ "optional": true
},
"node_modules/content-disposition": {
"version": "0.5.4",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
- "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
"license": "MIT",
"dependencies": {
"safe-buffer": "5.2.1"
@@ -3856,269 +5010,13 @@
},
"node_modules/content-type": {
"version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
- "node_modules/conventional-changelog": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-4.0.0.tgz",
- "integrity": "sha512-JbZjwE1PzxQCvm+HUTIr+pbSekS8qdOZzMakdFyPtdkEWwFvwEJYONzjgMm0txCb2yBcIcfKDmg8xtCKTdecNQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "conventional-changelog-angular": "^6.0.0",
- "conventional-changelog-atom": "^3.0.0",
- "conventional-changelog-codemirror": "^3.0.0",
- "conventional-changelog-conventionalcommits": "^6.0.0",
- "conventional-changelog-core": "^5.0.0",
- "conventional-changelog-ember": "^3.0.0",
- "conventional-changelog-eslint": "^4.0.0",
- "conventional-changelog-express": "^3.0.0",
- "conventional-changelog-jquery": "^4.0.0",
- "conventional-changelog-jshint": "^3.0.0",
- "conventional-changelog-preset-loader": "^3.0.0"
- },
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-changelog-angular": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz",
- "integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "compare-func": "^2.0.0"
- },
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-changelog-atom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-3.0.0.tgz",
- "integrity": "sha512-pnN5bWpH+iTUWU3FaYdw5lJmfWeqSyrUkG+wyHBI9tC1dLNnHkbAOg1SzTQ7zBqiFrfo55h40VsGXWMdopwc5g==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-changelog-codemirror": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-3.0.0.tgz",
- "integrity": "sha512-wzchZt9HEaAZrenZAUUHMCFcuYzGoZ1wG/kTRMICxsnW5AXohYMRxnyecP9ob42Gvn5TilhC0q66AtTPRSNMfw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-changelog-config-spec": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz",
- "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/conventional-changelog-conventionalcommits": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-6.1.0.tgz",
- "integrity": "sha512-3cS3GEtR78zTfMzk0AizXKKIdN4OvSh7ibNz6/DPbhWWQu7LqE/8+/GqSodV+sywUR2gpJAdP/1JFf4XtN7Zpw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "compare-func": "^2.0.0"
- },
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-changelog-core": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-5.0.2.tgz",
- "integrity": "sha512-RhQOcDweXNWvlRwUDCpaqXzbZemKPKncCWZG50Alth72WITVd6nhVk9MJ6w1k9PFNBcZ3YwkdkChE+8+ZwtUug==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "add-stream": "^1.0.0",
- "conventional-changelog-writer": "^6.0.0",
- "conventional-commits-parser": "^4.0.0",
- "dateformat": "^3.0.3",
- "get-pkg-repo": "^4.2.1",
- "git-raw-commits": "^3.0.0",
- "git-remote-origin-url": "^2.0.0",
- "git-semver-tags": "^5.0.0",
- "normalize-package-data": "^3.0.3",
- "read-pkg": "^3.0.0",
- "read-pkg-up": "^3.0.0"
- },
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-changelog-ember": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-3.0.0.tgz",
- "integrity": "sha512-7PYthCoSxIS98vWhVcSphMYM322OxptpKAuHYdVspryI0ooLDehRXWeRWgN+zWSBXKl/pwdgAg8IpLNSM1/61A==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-changelog-eslint": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-4.0.0.tgz",
- "integrity": "sha512-nEZ9byP89hIU0dMx37JXQkE1IpMmqKtsaR24X7aM3L6Yy/uAtbb+ogqthuNYJkeO1HyvK7JsX84z8649hvp43Q==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-changelog-express": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-3.0.0.tgz",
- "integrity": "sha512-HqxihpUMfIuxvlPvC6HltA4ZktQEUan/v3XQ77+/zbu8No/fqK3rxSZaYeHYant7zRxQNIIli7S+qLS9tX9zQA==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-changelog-jquery": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-4.0.0.tgz",
- "integrity": "sha512-TTIN5CyzRMf8PUwyy4IOLmLV2DFmPtasKN+x7EQKzwSX8086XYwo+NeaeA3VUT8bvKaIy5z/JoWUvi7huUOgaw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-changelog-jshint": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-3.0.0.tgz",
- "integrity": "sha512-bQof4byF4q+n+dwFRkJ/jGf9dCNUv4/kCDcjeCizBvfF81TeimPZBB6fT4HYbXgxxfxWXNl/i+J6T0nI4by6DA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "compare-func": "^2.0.0"
- },
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-changelog-preset-loader": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-3.0.0.tgz",
- "integrity": "sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-changelog-writer": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-6.0.1.tgz",
- "integrity": "sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "conventional-commits-filter": "^3.0.0",
- "dateformat": "^3.0.3",
- "handlebars": "^4.7.7",
- "json-stringify-safe": "^5.0.1",
- "meow": "^8.1.2",
- "semver": "^7.0.0",
- "split": "^1.0.1"
- },
- "bin": {
- "conventional-changelog-writer": "cli.js"
- },
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-changelog-writer/node_modules/semver": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
- "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/conventional-commits-filter": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-3.0.0.tgz",
- "integrity": "sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "lodash.ismatch": "^4.4.0",
- "modify-values": "^1.0.1"
- },
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-commits-parser": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz",
- "integrity": "sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-text-path": "^1.0.1",
- "JSONStream": "^1.3.5",
- "meow": "^8.1.2",
- "split2": "^3.2.2"
- },
- "bin": {
- "conventional-commits-parser": "cli.js"
- },
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/conventional-recommended-bump": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-7.0.1.tgz",
- "integrity": "sha512-Ft79FF4SlOFvX4PkwFDRnaNiIVX7YbmqGU0RwccUaiGvgp3S0a8ipR2/Qxk31vclDNM+GSdJOVs2KrsUCjblVA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "concat-stream": "^2.0.0",
- "conventional-changelog-preset-loader": "^3.0.0",
- "conventional-commits-filter": "^3.0.0",
- "conventional-commits-parser": "^4.0.0",
- "git-raw-commits": "^3.0.0",
- "git-semver-tags": "^5.0.0",
- "meow": "^8.1.2"
- },
- "bin": {
- "conventional-recommended-bump": "cli.js"
- },
- "engines": {
- "node": ">=14"
- }
- },
"node_modules/convert-hrtime": {
"version": "5.0.0",
- "resolved": "https://registry.npmjs.org/convert-hrtime/-/convert-hrtime-5.0.0.tgz",
- "integrity": "sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==",
"license": "MIT",
"engines": {
"node": ">=12"
@@ -4127,16 +5025,8 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/convert-source-map": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
- "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
- "license": "MIT"
- },
"node_modules/cookie": {
"version": "0.7.1",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
- "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -4144,52 +5034,17 @@
},
"node_modules/cookie-signature": {
"version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
"license": "MIT"
},
- "node_modules/core-util-is": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
- "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "node_modules/create-require": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true,
"license": "MIT"
},
- "node_modules/cosmiconfig": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
- "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
- "license": "MIT",
- "dependencies": {
- "@types/parse-json": "^4.0.0",
- "import-fresh": "^3.2.1",
- "parse-json": "^5.0.0",
- "path-type": "^4.0.0",
- "yaml": "^1.10.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/cpu-features": {
- "version": "0.0.10",
- "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz",
- "integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "dependencies": {
- "buildcheck": "~0.0.6",
- "nan": "^2.19.0"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
"node_modules/cross-env": {
"version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
- "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4207,8 +5062,6 @@
},
"node_modules/cross-spawn": {
"version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4220,19 +5073,24 @@
"node": ">= 8"
}
},
- "node_modules/crypto-js": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz",
- "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==",
- "dev": true,
- "license": "MIT"
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
},
"node_modules/cssstyle": {
"version": "4.3.0",
- "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.3.0.tgz",
- "integrity": "sha512-6r0NiY0xizYqfBvWp1G7WXJ06/bZyrk7Dc6PHql82C/pKGUTKu4yAX4Y8JPamb1ob9nBKuxWzCGTRuGwU3yxJQ==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"@asamuzakjp/css-color": "^3.1.1",
"rrweb-cssom": "^0.8.0"
@@ -4243,10 +5101,10 @@
},
"node_modules/cssstyle/node_modules/rrweb-cssom": {
"version": "0.8.0",
- "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz",
- "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/csstype": {
"version": "3.1.3",
@@ -4261,29 +5119,12 @@
"dev": true,
"license": "BSD-2-Clause"
},
- "node_modules/dargs": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz",
- "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/data-uri-to-buffer": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz",
- "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/data-urls": {
"version": "5.0.0",
- "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz",
- "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"whatwg-mimetype": "^4.0.0",
"whatwg-url": "^14.0.0"
@@ -4346,31 +5187,8 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/date-fns": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
- "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/kossnocorp"
- }
- },
- "node_modules/dateformat": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz",
- "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
"node_modules/debug": {
"version": "4.4.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
- "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
@@ -4384,60 +5202,54 @@
}
}
},
- "node_modules/decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+ "node_modules/decimal.js": {
+ "version": "10.5.0",
"dev": true,
"license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
+ "optional": true,
+ "peer": true
},
- "node_modules/decamelize-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz",
- "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==",
- "dev": true,
+ "node_modules/decode-named-character-reference": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz",
+ "integrity": "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==",
"license": "MIT",
"dependencies": {
- "decamelize": "^1.1.0",
- "map-obj": "^1.0.0"
+ "character-entities": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-response": "^3.1.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/decamelize-keys/node_modules/map-obj": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
- "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/decimal.js": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz",
- "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/deep-eql": {
"version": "5.0.2",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
- "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -4481,72 +5293,95 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/defu": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
- "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/delayed-stream": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=0.4.0"
}
},
+ "node_modules/delegates": {
+ "version": "1.0.0",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/depd": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/destroy": {
"version": "1.2.0",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
- "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"license": "MIT",
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
- "node_modules/detect-indent": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
- "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/detect-libc": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
- "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
+ "version": "2.0.4",
"license": "Apache-2.0",
- "optional": true,
"engines": {
"node": ">=8"
}
},
- "node_modules/detect-newline": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
- "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
- "dev": true,
+ "node_modules/detect-node-es": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
+ "license": "MIT"
+ },
+ "node_modules/devlop": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
+ "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
"license": "MIT",
- "engines": {
- "node": ">=8"
+ "dependencies": {
+ "dequal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/didyoumean": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/doctrine": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
@@ -4560,33 +5395,8 @@
"node": ">=0.10.0"
}
},
- "node_modules/dom-helpers": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
- "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.8.7",
- "csstype": "^3.0.2"
- }
- },
- "node_modules/dot-prop": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
- "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-obj": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/dotenv": {
"version": "16.4.7",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
- "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
@@ -4595,86 +5405,6 @@
"url": "https://dotenvx.com"
}
},
- "node_modules/dotgitignore": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz",
- "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "find-up": "^3.0.0",
- "minimatch": "^3.0.4"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/dotgitignore/node_modules/find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "locate-path": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/dotgitignore/node_modules/locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/dotgitignore/node_modules/p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-try": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/dotgitignore/node_modules/p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-limit": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/dotgitignore/node_modules/path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -4689,12 +5419,24 @@
"node": ">= 0.4"
}
},
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/ee-first": {
"version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"license": "MIT"
},
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.157",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.157.tgz",
+ "integrity": "sha512-/0ybgsQd1muo8QlnuTpKwtl0oX5YMlUGbm8xyqgDU00motRkKFFbUJySAQBWcY79rVqNLWIWa87BGVGClwAB2w==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
@@ -4704,23 +5446,45 @@
},
"node_modules/enabled": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
- "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==",
"license": "MIT"
},
"node_modules/encodeurl": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
- "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
+ "node_modules/encoding": {
+ "version": "0.1.13",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "iconv-lite": "^0.6.2"
+ }
+ },
+ "node_modules/encoding/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
"node_modules/enhanced-resolve": {
- "version": "5.18.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz",
- "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==",
+ "version": "5.18.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
+ "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4733,10 +5497,10 @@
},
"node_modules/entities": {
"version": "4.5.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
- "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"dev": true,
"license": "BSD-2-Clause",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=0.12"
},
@@ -4744,10 +5508,16 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/envalid": {
"version": "8.0.0",
- "resolved": "https://registry.npmjs.org/envalid/-/envalid-8.0.0.tgz",
- "integrity": "sha512-PGeYJnJB5naN0ME6SH8nFcDj9HVbLpYIfg1p5lAyM9T4cH2lwtu2fLbozC/bq+HUUOIFxhX/LP0/GmlqPHT4tQ==",
"license": "MIT",
"dependencies": {
"tslib": "2.6.2"
@@ -4758,29 +5528,17 @@
},
"node_modules/envalid/node_modules/tslib": {
"version": "2.6.2",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
- "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
"license": "0BSD"
},
- "node_modules/error-ex": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
- "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "node_modules/err-code": {
+ "version": "2.0.3",
"license": "MIT",
- "dependencies": {
- "is-arrayish": "^0.2.1"
- }
- },
- "node_modules/error-ex/node_modules/is-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
- "license": "MIT"
+ "optional": true
},
"node_modules/es-abstract": {
- "version": "1.23.7",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.7.tgz",
- "integrity": "sha512-OygGC8kIcDhXX+6yAZRGLqwi2CmEXCbLQixeGUgYeR+Qwlppqmo7DIDr8XibtEBZp+fJcoYpoatp5qwLMEdcqQ==",
+ "version": "1.23.9",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz",
+ "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4795,10 +5553,11 @@
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.0.0",
- "es-set-tostringtag": "^2.0.3",
+ "es-set-tostringtag": "^2.1.0",
"es-to-primitive": "^1.3.0",
"function.prototype.name": "^1.1.8",
- "get-intrinsic": "^1.2.6",
+ "get-intrinsic": "^1.2.7",
+ "get-proto": "^1.0.0",
"get-symbol-description": "^1.1.0",
"globalthis": "^1.0.4",
"gopd": "^1.2.0",
@@ -4819,9 +5578,12 @@
"object-inspect": "^1.13.3",
"object-keys": "^1.1.1",
"object.assign": "^4.1.7",
+ "own-keys": "^1.0.1",
"regexp.prototype.flags": "^1.5.3",
"safe-array-concat": "^1.1.3",
+ "safe-push-apply": "^1.0.0",
"safe-regex-test": "^1.1.0",
+ "set-proto": "^1.0.0",
"string.prototype.trim": "^1.2.10",
"string.prototype.trimend": "^1.0.9",
"string.prototype.trimstart": "^1.0.8",
@@ -4841,8 +5603,6 @@
},
"node_modules/es-define-property": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -4850,8 +5610,6 @@
},
"node_modules/es-errors": {
"version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -4887,15 +5645,13 @@
},
"node_modules/es-module-lexer": {
"version": "1.6.0",
- "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz",
- "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==",
"dev": true,
"license": "MIT"
},
"node_modules/es-object-atoms": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
- "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
@@ -4906,8 +5662,6 @@
},
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
- "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4921,13 +5675,16 @@
}
},
"node_modules/es-shim-unscopables": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
- "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
+ "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "hasown": "^2.0.0"
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
}
},
"node_modules/es-to-primitive": {
@@ -4950,8 +5707,6 @@
},
"node_modules/esbuild": {
"version": "0.23.1",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz",
- "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -5000,14 +5755,13 @@
},
"node_modules/escape-html": {
"version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"license": "MIT"
},
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
@@ -5017,22 +5771,23 @@
}
},
"node_modules/eslint": {
- "version": "9.17.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz",
- "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==",
+ "version": "9.27.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz",
+ "integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.19.0",
- "@eslint/core": "^0.9.0",
- "@eslint/eslintrc": "^3.2.0",
- "@eslint/js": "9.17.0",
- "@eslint/plugin-kit": "^0.2.3",
+ "@eslint/config-array": "^0.20.0",
+ "@eslint/config-helpers": "^0.2.1",
+ "@eslint/core": "^0.14.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.27.0",
+ "@eslint/plugin-kit": "^0.3.1",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
- "@humanwhocodes/retry": "^0.4.1",
+ "@humanwhocodes/retry": "^0.4.2",
"@types/estree": "^1.0.6",
"@types/json-schema": "^7.0.15",
"ajv": "^6.12.4",
@@ -5040,7 +5795,7 @@
"cross-spawn": "^7.0.6",
"debug": "^4.3.2",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^8.2.0",
+ "eslint-scope": "^8.3.0",
"eslint-visitor-keys": "^4.2.0",
"espree": "^10.3.0",
"esquery": "^1.5.0",
@@ -5077,13 +5832,13 @@
}
},
"node_modules/eslint-config-next": {
- "version": "15.1.2",
- "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.1.2.tgz",
- "integrity": "sha512-PrMm1/4zWSJ689wd/ypWIR5ZF1uvmp3EkgpgBV1Yu6PhEobBjXMGgT8bVNelwl17LXojO8D5ePFRiI4qXjsPRA==",
+ "version": "15.3.2",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.3.2.tgz",
+ "integrity": "sha512-FerU4DYccO4FgeYFFglz0SnaKRe1ejXQrDb8kWUkTAg036YWi+jUsgg4sIGNCDhAsDITsZaL4MzBWKB6f4G1Dg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@next/eslint-plugin-next": "15.1.2",
+ "@next/eslint-plugin-next": "15.3.2",
"@rushstack/eslint-patch": "^1.10.3",
"@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
"@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
@@ -5127,26 +5882,25 @@
}
},
"node_modules/eslint-import-resolver-typescript": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.7.0.tgz",
- "integrity": "sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow==",
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz",
+ "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==",
"dev": true,
"license": "ISC",
"dependencies": {
"@nolyfill/is-core-module": "1.0.39",
- "debug": "^4.3.7",
- "enhanced-resolve": "^5.15.0",
- "fast-glob": "^3.3.2",
- "get-tsconfig": "^4.7.5",
- "is-bun-module": "^1.0.2",
- "is-glob": "^4.0.3",
- "stable-hash": "^0.0.4"
+ "debug": "^4.4.0",
+ "get-tsconfig": "^4.10.0",
+ "is-bun-module": "^2.0.0",
+ "stable-hash": "^0.0.5",
+ "tinyglobby": "^0.2.13",
+ "unrs-resolver": "^1.6.2"
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
},
"funding": {
- "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts"
+ "url": "https://opencollective.com/eslint-import-resolver-typescript"
},
"peerDependencies": {
"eslint": "*",
@@ -5162,36 +5916,6 @@
}
}
},
- "node_modules/eslint-import-resolver-typescript/node_modules/fast-glob": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
- "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/eslint-import-resolver-typescript/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/eslint-module-utils": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz",
@@ -5264,6 +5988,16 @@
"ms": "^2.1.1"
}
},
+ "node_modules/eslint-plugin-import/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
"node_modules/eslint-plugin-jsx-a11y": {
"version": "6.10.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz",
@@ -5295,9 +6029,9 @@
}
},
"node_modules/eslint-plugin-react": {
- "version": "7.37.3",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.3.tgz",
- "integrity": "sha512-DomWuTQPFYZwF/7c9W2fkKkStqZmBd3uugfqBYLdkZ3Hii23WzZuOLUskGxB8qkSKqftxEeGL1TB2kMhrce0jA==",
+ "version": "7.37.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
+ "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5311,7 +6045,7 @@
"hasown": "^2.0.2",
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
"minimatch": "^3.1.2",
- "object.entries": "^1.1.8",
+ "object.entries": "^1.1.9",
"object.fromentries": "^2.0.8",
"object.values": "^1.2.1",
"prop-types": "^15.8.1",
@@ -5328,9 +6062,9 @@
}
},
"node_modules/eslint-plugin-react-hooks": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0.tgz",
- "integrity": "sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==",
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz",
+ "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -5358,10 +6092,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/eslint-plugin-react/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
"node_modules/eslint-scope": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz",
- "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==",
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
+ "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
@@ -5442,10 +6186,18 @@
"node": ">=4.0"
}
},
+ "node_modules/estree-util-is-identifier-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz",
+ "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/estree-walker": {
"version": "3.0.3",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
- "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5464,40 +6216,34 @@
},
"node_modules/etag": {
"version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
- "node_modules/exit-hook": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz",
- "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==",
- "dev": true,
- "license": "MIT",
+ "node_modules/expand-template": {
+ "version": "2.0.3",
+ "license": "(MIT OR WTFPL)",
"engines": {
"node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/expect-type": {
"version": "1.1.0",
- "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz",
- "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">=12.0.0"
}
},
+ "node_modules/expr-eval": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/expr-eval/-/expr-eval-2.0.2.tgz",
+ "integrity": "sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg==",
+ "license": "MIT"
+ },
"node_modules/express": {
"version": "4.21.2",
- "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
- "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
@@ -5540,10 +6286,21 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/express-rate-limit": {
+ "version": "7.5.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/express-rate-limit"
+ },
+ "peerDependencies": {
+ "express": "^4.11 || 5 || ^5.0.0-beta.1"
+ }
+ },
"node_modules/express/node_modules/debug": {
"version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
@@ -5551,8 +6308,12 @@
},
"node_modules/express/node_modules/ms": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"license": "MIT"
},
"node_modules/fast-deep-equal": {
@@ -5607,9 +6368,9 @@
"license": "MIT"
},
"node_modules/fastq": {
- "version": "1.18.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
- "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==",
+ "version": "1.19.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
+ "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -5618,36 +6379,8 @@
},
"node_modules/fecha": {
"version": "4.2.3",
- "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
- "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==",
"license": "MIT"
},
- "node_modules/figures": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
- "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "escape-string-regexp": "^1.0.5"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/figures/node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -5661,6 +6394,10 @@
"node": ">=16.0.0"
}
},
+ "node_modules/file-uri-to-path": {
+ "version": "1.0.0",
+ "license": "MIT"
+ },
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@@ -5676,8 +6413,6 @@
},
"node_modules/finalhandler": {
"version": "1.3.1",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
- "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
@@ -5694,8 +6429,6 @@
},
"node_modules/finalhandler/node_modules/debug": {
"version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
@@ -5703,14 +6436,6 @@
},
"node_modules/finalhandler/node_modules/ms": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/find-root": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
- "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
"license": "MIT"
},
"node_modules/find-up": {
@@ -5745,34 +6470,68 @@
}
},
"node_modules/flatted": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz",
- "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
"dev": true,
"license": "ISC"
},
"node_modules/fn.name": {
"version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
- "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==",
"license": "MIT"
},
"node_modules/for-each": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
- "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "is-callable": "^1.1.3"
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/foreground-child/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/form-data": {
"version": "4.0.2",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
- "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -5785,28 +6544,77 @@
},
"node_modules/forwarded": {
"version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
+ "node_modules/fraction.js": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
+ "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://github.com/sponsors/rawify"
+ }
+ },
+ "node_modules/framer-motion": {
+ "version": "12.12.2",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.12.2.tgz",
+ "integrity": "sha512-qCszZCiGWkilL40E3VuhIJJC/CS3SIBl2IHyGK8FU30nOUhTmhBNWPrNFyozAWH/bXxwzi19vJHIGVdALF0LCg==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-dom": "^12.12.1",
+ "motion-utils": "^12.12.1",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/fresh": {
"version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "license": "MIT"
+ },
+ "node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
"node_modules/fs.realpath": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true,
- "license": "ISC"
+ "license": "ISC",
+ "optional": true
},
"node_modules/fsevents": {
"version": "2.3.3",
@@ -5825,8 +6633,6 @@
},
"node_modules/function-bind": {
"version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -5834,8 +6640,6 @@
},
"node_modules/function-timeout": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/function-timeout/-/function-timeout-1.0.2.tgz",
- "integrity": "sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA==",
"license": "MIT",
"engines": {
"node": ">=18"
@@ -5875,32 +6679,40 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true,
+ "node_modules/gauge": {
+ "version": "4.0.4",
"license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.3",
+ "console-control-strings": "^1.1.0",
+ "has-unicode": "^2.0.1",
+ "signal-exit": "^3.0.7",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.5"
+ },
"engines": {
- "node": "6.* || 8.* || >= 10.*"
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
}
},
"node_modules/get-intrinsic": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz",
- "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "dunder-proto": "^1.0.0",
+ "call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
- "es-object-atoms": "^1.0.0",
+ "es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
- "math-intrinsics": "^1.0.0"
+ "math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
@@ -5909,65 +6721,26 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/get-pkg-repo": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz",
- "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==",
- "dev": true,
+ "node_modules/get-nonce": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
+ "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
- "@hutson/parse-repository-url": "^3.0.0",
- "hosted-git-info": "^4.0.0",
- "through2": "^2.0.0",
- "yargs": "^16.2.0"
- },
- "bin": {
- "get-pkg-repo": "src/cli.js"
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
},
"engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/get-pkg-repo/node_modules/cliui": {
- "version": "7.0.4",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
- "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.0",
- "wrap-ansi": "^7.0.0"
- }
- },
- "node_modules/get-pkg-repo/node_modules/yargs": {
- "version": "16.2.0",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
- "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cliui": "^7.0.2",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.0",
- "y18n": "^5.0.5",
- "yargs-parser": "^20.2.2"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/get-source": {
- "version": "2.0.12",
- "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz",
- "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==",
- "dev": true,
- "license": "Unlicense",
- "dependencies": {
- "data-uri-to-buffer": "^2.0.0",
- "source-map": "^0.6.1"
+ "node": ">= 0.4"
}
},
"node_modules/get-symbol-description": {
@@ -5989,9 +6762,9 @@
}
},
"node_modules/get-tsconfig": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz",
- "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==",
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz",
+ "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6001,85 +6774,14 @@
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
- "node_modules/git-raw-commits": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-3.0.0.tgz",
- "integrity": "sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "dargs": "^7.0.0",
- "meow": "^8.1.2",
- "split2": "^3.2.2"
- },
- "bin": {
- "git-raw-commits": "cli.js"
- },
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/git-remote-origin-url": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz",
- "integrity": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "gitconfiglocal": "^1.0.0",
- "pify": "^2.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/git-semver-tags": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-5.0.1.tgz",
- "integrity": "sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "meow": "^8.1.2",
- "semver": "^7.0.0"
- },
- "bin": {
- "git-semver-tags": "cli.js"
- },
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/git-semver-tags/node_modules/semver": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
- "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/gitconfiglocal": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz",
- "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==",
- "dev": true,
- "license": "BSD",
- "dependencies": {
- "ini": "^1.3.2"
- }
+ "node_modules/github-from-package": {
+ "version": "0.0.0",
+ "license": "MIT"
},
"node_modules/glob": {
"version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "dev": true,
"license": "ISC",
+ "optional": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -6108,13 +6810,6 @@
"node": ">=10.13.0"
}
},
- "node_modules/glob-to-regexp": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
- "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
- "dev": true,
- "license": "BSD-2-Clause"
- },
"node_modules/globals": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
@@ -6147,8 +6842,6 @@
},
"node_modules/gopd": {
"version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -6159,9 +6852,7 @@
},
"node_modules/graceful-fs": {
"version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "dev": true,
+ "devOptional": true,
"license": "ISC"
},
"node_modules/graphemer": {
@@ -6171,38 +6862,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/handlebars": {
- "version": "4.7.8",
- "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
- "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "minimist": "^1.2.5",
- "neo-async": "^2.6.2",
- "source-map": "^0.6.1",
- "wordwrap": "^1.0.0"
- },
- "bin": {
- "handlebars": "bin/handlebars"
- },
- "engines": {
- "node": ">=0.4.7"
- },
- "optionalDependencies": {
- "uglify-js": "^3.1.4"
- }
- },
- "node_modules/hard-rejection": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
- "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/has-bigints": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
@@ -6257,8 +6916,6 @@
},
"node_modules/has-symbols": {
"version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -6269,8 +6926,6 @@
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
- "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6283,10 +6938,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/has-unicode": {
+ "version": "2.0.1",
+ "license": "ISC",
+ "optional": true
+ },
"node_modules/hasown": {
"version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@@ -6295,34 +6953,52 @@
"node": ">= 0.4"
}
},
- "node_modules/hoist-non-react-statics": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
- "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
- "license": "BSD-3-Clause",
+ "node_modules/hast-util-to-jsx-runtime": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
+ "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==",
+ "license": "MIT",
"dependencies": {
- "react-is": "^16.7.0"
+ "@types/estree": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "devlop": "^1.0.0",
+ "estree-util-is-identifier-name": "^3.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "mdast-util-mdx-expression": "^2.0.0",
+ "mdast-util-mdx-jsx": "^3.0.0",
+ "mdast-util-mdxjs-esm": "^2.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "style-to-js": "^1.0.0",
+ "unist-util-position": "^5.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
- "node_modules/hosted-git-info": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
- "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
- "dev": true,
- "license": "ISC",
+ "node_modules/hast-util-whitespace": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
+ "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
+ "license": "MIT",
"dependencies": {
- "lru-cache": "^6.0.0"
+ "@types/hast": "^3.0.0"
},
- "engines": {
- "node": ">=10"
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
"node_modules/html-encoding-sniffer": {
"version": "4.0.0",
- "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
- "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"whatwg-encoding": "^3.1.1"
},
@@ -6330,10 +7006,23 @@
"node": ">=18"
}
},
+ "node_modules/html-url-attributes": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
+ "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/http-cache-semantics": {
+ "version": "4.2.0",
+ "license": "BSD-2-Clause",
+ "optional": true
+ },
"node_modules/http-errors": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
- "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"license": "MIT",
"dependencies": {
"depd": "2.0.0",
@@ -6348,10 +7037,10 @@
},
"node_modules/http-proxy-agent": {
"version": "7.0.2",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
- "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"agent-base": "^7.1.0",
"debug": "^4.3.4"
@@ -6362,10 +7051,10 @@
},
"node_modules/https-proxy-agent": {
"version": "7.0.6",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
- "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"agent-base": "^7.1.2",
"debug": "4"
@@ -6374,10 +7063,16 @@
"node": ">= 14"
}
},
+ "node_modules/humanize-ms": {
+ "version": "1.2.1",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "ms": "^2.0.0"
+ }
+ },
"node_modules/iconv-lite": {
"version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
@@ -6386,6 +7081,24 @@
"node": ">=0.10.0"
}
},
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -6397,9 +7110,10 @@
}
},
"node_modules/import-fresh": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
- "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"parent-module": "^1.0.0",
@@ -6414,9 +7128,7 @@
},
"node_modules/imurmurhash": {
"version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=0.8.19"
@@ -6424,21 +7136,21 @@
},
"node_modules/indent-string": {
"version": "4.0.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
- "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
- "dev": true,
"license": "MIT",
+ "optional": true,
"engines": {
"node": ">=8"
}
},
+ "node_modules/infer-owner": {
+ "version": "1.0.4",
+ "license": "ISC",
+ "optional": true
+ },
"node_modules/inflight": {
"version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
- "dev": true,
"license": "ISC",
+ "optional": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
@@ -6446,17 +7158,18 @@
},
"node_modules/inherits": {
"version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/ini": {
"version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "dev": true,
"license": "ISC"
},
+ "node_modules/inline-style-parser": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz",
+ "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==",
+ "license": "MIT"
+ },
"node_modules/internal-slot": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
@@ -6472,15 +7185,49 @@
"node": ">= 0.4"
}
},
+ "node_modules/ip-address": {
+ "version": "9.0.5",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "jsbn": "1.1.0",
+ "sprintf-js": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 12"
+ }
+ },
"node_modules/ipaddr.js": {
"version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
"license": "MIT",
"engines": {
"node": ">= 0.10"
}
},
+ "node_modules/is-alphabetical": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
+ "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-alphanumerical": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz",
+ "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==",
+ "license": "MIT",
+ "dependencies": {
+ "is-alphabetical": "^2.0.0",
+ "is-decimal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/is-array-buffer": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
@@ -6501,18 +7248,20 @@
},
"node_modules/is-arrayish": {
"version": "0.3.2",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
- "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
"license": "MIT"
},
"node_modules/is-async-function": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
- "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+ "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "has-tostringtag": "^1.0.0"
+ "async-function": "^1.0.0",
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
@@ -6537,14 +7286,27 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-boolean-object": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz",
- "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==",
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2",
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+ "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
"has-tostringtag": "^1.0.2"
},
"engines": {
@@ -6555,26 +7317,13 @@
}
},
"node_modules/is-bun-module": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz",
- "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz",
+ "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "semver": "^7.6.3"
- }
- },
- "node_modules/is-bun-module/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
+ "semver": "^7.7.1"
}
},
"node_modules/is-callable": {
@@ -6594,6 +7343,7 @@
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"hasown": "^2.0.2"
@@ -6640,6 +7390,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-decimal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
+ "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -6668,22 +7428,23 @@
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/is-generator-function": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
- "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
+ "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "has-tostringtag": "^1.0.0"
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.0",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
@@ -6705,6 +7466,21 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-hexadecimal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz",
+ "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/is-lambda": {
+ "version": "1.0.1",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/is-map": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
@@ -6745,32 +7521,24 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-obj": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
- "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/is-plain-obj": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
- "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
- "dev": true,
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
+ "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
"license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-potential-custom-element-name": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
- "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/is-regex": {
"version": "1.2.1",
@@ -6822,8 +7590,6 @@
},
"node_modules/is-stream": {
"version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
- "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"license": "MIT",
"engines": {
"node": ">=8"
@@ -6867,19 +7633,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-text-path": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz",
- "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "text-extensions": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/is-typed-array": {
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
@@ -6910,13 +7663,13 @@
}
},
"node_modules/is-weakref": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz",
- "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+ "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bound": "^1.0.2"
+ "call-bound": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
@@ -6951,40 +7704,58 @@
},
"node_modules/isexe": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true,
+ "devOptional": true,
"license": "ISC"
},
"node_modules/iterator.prototype": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.4.tgz",
- "integrity": "sha512-x4WH0BWmrMmg4oHHl+duwubhrvczGlyuGAZu3nvrf0UXOfPu8IhZObFEr7DE/iv01YgVZrsOiRcqw2srkKEDIA==",
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
+ "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
"dev": true,
"license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
"es-object-atoms": "^1.0.0",
"get-intrinsic": "^1.2.6",
+ "get-proto": "^1.0.0",
"has-symbols": "^1.1.0",
- "reflect.getprototypeof": "^1.0.8",
"set-function-name": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
- "node_modules/itty-time": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/itty-time/-/itty-time-1.0.6.tgz",
- "integrity": "sha512-+P8IZaLLBtFv8hCkIjcymZOp4UJ+xW6bSlQsXGqrkmJh7vSiMFSlNne0mCYagEE0N7HDNR5jJBRxwN0oYv61Rw==",
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"dev": true,
- "license": "MIT"
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
+ "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
"license": "MIT"
},
"node_modules/js-yaml": {
@@ -7000,12 +7771,17 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/jsbn": {
+ "version": "1.1.0",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/jsdom": {
"version": "25.0.1",
- "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz",
- "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"cssstyle": "^4.1.0",
"data-urls": "^5.0.0",
@@ -7041,18 +7817,6 @@
}
}
},
- "node_modules/jsesc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
- "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
- "license": "MIT",
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
@@ -7060,19 +7824,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/json-parse-better-errors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
- "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json-parse-even-better-errors": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
- "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
- "license": "MIT"
- },
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -7087,13 +7838,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/json-stringify-safe": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
- "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/json5": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
@@ -7107,39 +7851,6 @@
"json5": "lib/cli.js"
}
},
- "node_modules/jsoncrush": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/jsoncrush/-/jsoncrush-1.1.8.tgz",
- "integrity": "sha512-lvIMGzMUA0fjuqwNcxlTNRq2bibPZ9auqT/LyGdlR5hvydJtA/BasSgkx4qclqTKVeTidrJvsS/oVjlTCPQ4Nw==",
- "license": "MIT"
- },
- "node_modules/jsonparse": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
- "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
- "dev": true,
- "engines": [
- "node >= 0.2.0"
- ],
- "license": "MIT"
- },
- "node_modules/JSONStream": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
- "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
- "dev": true,
- "license": "(MIT OR Apache-2.0)",
- "dependencies": {
- "jsonparse": "^1.2.0",
- "through": ">=2.2.7 <3"
- },
- "bin": {
- "JSONStream": "bin.js"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/jsx-ast-utils": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
@@ -7166,20 +7877,8 @@
"json-buffer": "3.0.1"
}
},
- "node_modules/kind-of": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
- "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/kuler": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
- "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==",
"license": "MIT"
},
"node_modules/language-subtag-registry": {
@@ -7216,52 +7915,275 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/lightningcss": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
+ "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-darwin-arm64": "1.30.1",
+ "lightningcss-darwin-x64": "1.30.1",
+ "lightningcss-freebsd-x64": "1.30.1",
+ "lightningcss-linux-arm-gnueabihf": "1.30.1",
+ "lightningcss-linux-arm64-gnu": "1.30.1",
+ "lightningcss-linux-arm64-musl": "1.30.1",
+ "lightningcss-linux-x64-gnu": "1.30.1",
+ "lightningcss-linux-x64-musl": "1.30.1",
+ "lightningcss-win32-arm64-msvc": "1.30.1",
+ "lightningcss-win32-x64-msvc": "1.30.1"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz",
+ "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz",
+ "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz",
+ "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz",
+ "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz",
+ "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz",
+ "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz",
+ "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz",
+ "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz",
+ "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.30.1",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz",
+ "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lilconfig": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
+ "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
+ }
+ },
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true,
"license": "MIT"
},
- "node_modules/load-json-file": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
- "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^4.0.0",
- "pify": "^3.0.0",
- "strip-bom": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/load-json-file/node_modules/parse-json": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/load-json-file/node_modules/pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -7278,24 +8200,26 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/lodash.ismatch": {
+ "node_modules/lodash.castarray": {
"version": "4.4.0",
- "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz",
- "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==",
- "dev": true,
+ "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
+ "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
"license": "MIT"
},
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true,
"license": "MIT"
},
"node_modules/logform": {
"version": "2.7.0",
- "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz",
- "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==",
"license": "MIT",
"dependencies": {
"@colors/colors": "1.6.0",
@@ -7309,10 +8233,21 @@
"node": ">= 12.0.0"
}
},
+ "node_modules/longest-streak": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
+ "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
@@ -7323,17 +8258,13 @@
},
"node_modules/loupe": {
"version": "3.1.2",
- "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz",
- "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==",
"dev": true,
"license": "MIT"
},
"node_modules/lru-cache": {
"version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "dev": true,
"license": "ISC",
+ "optional": true,
"dependencies": {
"yallist": "^4.0.0"
},
@@ -7341,239 +8272,261 @@
"node": ">=10"
}
},
+ "node_modules/lucide-react": {
+ "version": "0.511.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.511.0.tgz",
+ "integrity": "sha512-VK5a2ydJ7xm8GvBeKLS9mu1pVK6ucef9780JVUjw6bAjJL/QXnd4Y0p7SPeOUMC27YhzNCZvm5d/QX0Tp3rc0w==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/magic-string": {
"version": "0.30.17",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
- "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
- "node_modules/make-dir": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
- "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "node_modules/make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true,
- "license": "MIT",
+ "license": "ISC"
+ },
+ "node_modules/make-fetch-happen": {
+ "version": "9.1.0",
+ "license": "ISC",
+ "optional": true,
"dependencies": {
- "semver": "^6.0.0"
+ "agentkeepalive": "^4.1.3",
+ "cacache": "^15.2.0",
+ "http-cache-semantics": "^4.1.0",
+ "http-proxy-agent": "^4.0.1",
+ "https-proxy-agent": "^5.0.0",
+ "is-lambda": "^1.0.1",
+ "lru-cache": "^6.0.0",
+ "minipass": "^3.1.3",
+ "minipass-collect": "^1.0.2",
+ "minipass-fetch": "^1.3.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "negotiator": "^0.6.2",
+ "promise-retry": "^2.0.1",
+ "socks-proxy-agent": "^6.0.0",
+ "ssri": "^8.0.0"
},
"engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">= 10"
}
},
- "node_modules/map-obj": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz",
- "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
- "dev": true,
+ "node_modules/make-fetch-happen/node_modules/agent-base": {
+ "version": "6.0.2",
"license": "MIT",
- "engines": {
- "node": ">=8"
+ "optional": true,
+ "dependencies": {
+ "debug": "4"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/make-fetch-happen/node_modules/http-proxy-agent": {
+ "version": "4.0.1",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@tootallnate/once": "1",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/make-fetch-happen/node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
- "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
- "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
+ "node_modules/mdast-util-from-markdown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
+ "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-to-string": "^4.0.0",
+ "micromark": "^4.0.0",
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
+ "micromark-util-decode-string": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unist-util-stringify-position": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdx-expression": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz",
+ "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdx-jsx": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz",
+ "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "devlop": "^1.1.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0",
+ "parse-entities": "^4.0.0",
+ "stringify-entities": "^4.0.0",
+ "unist-util-stringify-position": "^4.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-mdxjs-esm": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz",
+ "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree-jsx": "^1.0.0",
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "mdast-util-to-markdown": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-phrasing": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz",
+ "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-hast": {
+ "version": "13.2.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz",
+ "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@ungap/structured-clone": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "trim-lines": "^3.0.0",
+ "unist-util-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-markdown": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz",
+ "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "@types/unist": "^3.0.0",
+ "longest-streak": "^3.0.0",
+ "mdast-util-phrasing": "^4.0.0",
+ "mdast-util-to-string": "^4.0.0",
+ "micromark-util-classify-character": "^2.0.0",
+ "micromark-util-decode-string": "^2.0.0",
+ "unist-util-visit": "^5.0.0",
+ "zwitch": "^2.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdast-util-to-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
+ "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mdast": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/media-typer": {
"version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
- "node_modules/memoize-one": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
- "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==",
- "license": "MIT"
- },
- "node_modules/meow": {
- "version": "8.1.2",
- "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz",
- "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/minimist": "^1.2.0",
- "camelcase-keys": "^6.2.2",
- "decamelize-keys": "^1.1.0",
- "hard-rejection": "^2.1.0",
- "minimist-options": "4.1.0",
- "normalize-package-data": "^3.0.0",
- "read-pkg-up": "^7.0.1",
- "redent": "^3.0.0",
- "trim-newlines": "^3.0.0",
- "type-fest": "^0.18.0",
- "yargs-parser": "^20.2.3"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/meow/node_modules/find-up": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
- "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/meow/node_modules/hosted-git-info": {
- "version": "2.8.9",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
- "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/meow/node_modules/locate-path": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
- "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-locate": "^4.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/meow/node_modules/p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-try": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/meow/node_modules/p-locate": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
- "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-limit": "^2.2.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/meow/node_modules/read-pkg": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
- "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/normalize-package-data": "^2.4.0",
- "normalize-package-data": "^2.5.0",
- "parse-json": "^5.0.0",
- "type-fest": "^0.6.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/meow/node_modules/read-pkg-up": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
- "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "find-up": "^4.1.0",
- "read-pkg": "^5.2.0",
- "type-fest": "^0.8.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
- "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
- "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "hosted-git-info": "^2.1.4",
- "resolve": "^1.10.0",
- "semver": "2 || 3 || 4 || 5",
- "validate-npm-package-license": "^3.0.1"
- }
- },
- "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
- "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/meow/node_modules/semver": {
- "version": "5.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
- "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver"
- }
- },
"node_modules/merge-descriptors": {
"version": "1.0.3",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
- "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -7591,13 +8544,453 @@
},
"node_modules/methods": {
"version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
+ "node_modules/micromark": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
+ "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@types/debug": "^4.0.0",
+ "debug": "^4.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-core-commonmark": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-combine-extensions": "^2.0.0",
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-resolve-all": "^2.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "micromark-util-subtokenize": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-core-commonmark": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz",
+ "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decode-named-character-reference": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-factory-destination": "^2.0.0",
+ "micromark-factory-label": "^2.0.0",
+ "micromark-factory-space": "^2.0.0",
+ "micromark-factory-title": "^2.0.0",
+ "micromark-factory-whitespace": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-classify-character": "^2.0.0",
+ "micromark-util-html-tag-name": "^2.0.0",
+ "micromark-util-normalize-identifier": "^2.0.0",
+ "micromark-util-resolve-all": "^2.0.0",
+ "micromark-util-subtokenize": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-factory-destination": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
+ "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-factory-label": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz",
+ "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-factory-space": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz",
+ "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-factory-title": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz",
+ "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-factory-whitespace": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz",
+ "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-factory-space": "^2.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-character": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
+ "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-chunked": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz",
+ "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-classify-character": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz",
+ "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-combine-extensions": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz",
+ "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-decode-numeric-character-reference": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz",
+ "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-decode-string": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz",
+ "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decode-named-character-reference": "^1.0.0",
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-decode-numeric-character-reference": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-encode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
+ "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-html-tag-name": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz",
+ "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-normalize-identifier": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz",
+ "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-resolve-all": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz",
+ "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-sanitize-uri": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
+ "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-subtokenize": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz",
+ "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "devlop": "^1.0.0",
+ "micromark-util-chunked": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-symbol": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
+ "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-types": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
+ "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==",
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
@@ -7614,8 +9007,6 @@
},
"node_modules/mime": {
"version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"license": "MIT",
"bin": {
"mime": "cli.js"
@@ -7626,8 +9017,6 @@
},
"node_modules/mime-db": {
"version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -7635,8 +9024,6 @@
},
"node_modules/mime-types": {
"version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
@@ -7645,61 +9032,28 @@
"node": ">= 0.6"
}
},
- "node_modules/min-indent": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
- "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
- "dev": true,
+ "node_modules/mimic-response": {
+ "version": "3.1.0",
"license": "MIT",
"engines": {
- "node": ">=4"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/miniflare": {
- "version": "3.20241230.0",
- "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20241230.0.tgz",
- "integrity": "sha512-ZtWNoNAIj5Q0Vb3B4SPEKr7DDmVG8a0Stsp/AuRkYXoJniA5hsbKjFNIGhTXGMIHVP5bvDrKJWt/POIDGfpiKg==",
- "dev": true,
+ "node_modules/mini-svg-data-uri": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
+ "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
"license": "MIT",
- "dependencies": {
- "@cspotcode/source-map-support": "0.8.1",
- "acorn": "^8.8.0",
- "acorn-walk": "^8.2.0",
- "capnp-ts": "^0.7.0",
- "exit-hook": "^2.2.1",
- "glob-to-regexp": "^0.4.1",
- "stoppable": "^1.1.0",
- "undici": "^5.28.4",
- "workerd": "1.20241230.0",
- "ws": "^8.18.0",
- "youch": "^3.2.2",
- "zod": "^3.22.3"
- },
"bin": {
- "miniflare": "bootstrap.js"
- },
- "engines": {
- "node": ">=16.13"
- }
- },
- "node_modules/miniflare/node_modules/undici": {
- "version": "5.28.5",
- "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
- "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@fastify/busboy": "^2.0.0"
- },
- "engines": {
- "node": ">=14.0"
+ "mini-svg-data-uri": "cli.js"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
+ "devOptional": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
@@ -7710,96 +9064,158 @@
},
"node_modules/minimist": {
"version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/minimist-options": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
- "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
- "dev": true,
- "license": "MIT",
+ "node_modules/minipass": {
+ "version": "3.3.6",
+ "license": "ISC",
"dependencies": {
- "arrify": "^1.0.1",
- "is-plain-obj": "^1.1.0",
- "kind-of": "^6.0.3"
+ "yallist": "^4.0.0"
},
"engines": {
- "node": ">= 6"
+ "node": ">=8"
}
},
- "node_modules/mlly": {
- "version": "1.7.4",
- "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz",
- "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==",
- "dev": true,
+ "node_modules/minipass-collect": {
+ "version": "1.0.2",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-fetch": {
+ "version": "1.4.1",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.1.0",
+ "minipass-sized": "^1.0.3",
+ "minizlib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "optionalDependencies": {
+ "encoding": "^0.1.12"
+ }
+ },
+ "node_modules/minipass-flush": {
+ "version": "1.0.5",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-pipeline": {
+ "version": "1.2.4",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-sized": {
+ "version": "1.0.3",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "2.1.2",
"license": "MIT",
"dependencies": {
- "acorn": "^8.14.0",
- "pathe": "^2.0.1",
- "pkg-types": "^1.3.0",
- "ufo": "^1.5.4"
- }
- },
- "node_modules/mlly/node_modules/pathe": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.1.tgz",
- "integrity": "sha512-6jpjMpOth5S9ITVu5clZ7NOgHNsv5vRQdheL9ztp2vZmM6fRbLvyua1tiBIL4lk8SAe3ARzeXEly6siXCjDHDw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/modify-values": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz",
- "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==",
- "dev": true,
- "license": "MIT",
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 8"
}
},
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mkdirp-classic": {
+ "version": "0.5.3",
+ "license": "MIT"
+ },
"node_modules/moment": {
"version": "2.30.1",
- "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
- "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
"license": "MIT",
"engines": {
"node": "*"
}
},
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
- "node_modules/mustache": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz",
- "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==",
- "dev": true,
+ "node_modules/moment-timezone": {
+ "version": "0.5.48",
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz",
+ "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==",
"license": "MIT",
- "bin": {
- "mustache": "bin/mustache"
+ "dependencies": {
+ "moment": "^2.29.4"
+ },
+ "engines": {
+ "node": "*"
}
},
- "node_modules/nan": {
- "version": "2.22.0",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz",
- "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==",
+ "node_modules/motion-dom": {
+ "version": "12.12.1",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.12.1.tgz",
+ "integrity": "sha512-GXq/uUbZBEiFFE+K1Z/sxdPdadMdfJ/jmBALDfIuHGi0NmtealLOfH9FqT+6aNPgVx8ilq0DtYmyQlo6Uj9LKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-utils": "^12.12.1"
+ }
+ },
+ "node_modules/motion-utils": {
+ "version": "12.12.1",
+ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.12.1.tgz",
+ "integrity": "sha512-f9qiqUHm7hWSLlNW8gS9pisnsN7CRFRD58vNjptKdsqFLpkVnX00TNeD6Q0d27V9KzT7ySFyK1TZ/DShfVOv6w==",
+ "license": "MIT"
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "license": "MIT"
+ },
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
"dev": true,
"license": "MIT",
- "optional": true
+ "dependencies": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
},
"node_modules/nanoid": {
"version": "3.3.8",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
- "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"funding": [
{
"type": "github",
@@ -7814,6 +9230,26 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
+ "node_modules/napi-build-utils": {
+ "version": "2.0.0",
+ "license": "MIT"
+ },
+ "node_modules/napi-postinstall": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.2.4.tgz",
+ "integrity": "sha512-ZEzHJwBhZ8qQSbknHqYcdtQVr8zUgGyM/q6h6qAyhtyVMNrSgDhrC4disf03dYW0e+czXyLnZINnCTEkWy0eJg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "napi-postinstall": "lib/cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/napi-postinstall"
+ }
+ },
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -7823,27 +9259,18 @@
},
"node_modules/negotiator": {
"version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
- "node_modules/neo-async": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
- "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/next": {
- "version": "15.1.2",
- "resolved": "https://registry.npmjs.org/next/-/next-15.1.2.tgz",
- "integrity": "sha512-nLJDV7peNy+0oHlmY2JZjzMfJ8Aj0/dd3jCwSZS8ZiO5nkQfcZRqDrRN3U5rJtqVTQneIOGZzb6LCNrk7trMCQ==",
+ "version": "15.3.2",
+ "resolved": "https://registry.npmjs.org/next/-/next-15.3.2.tgz",
+ "integrity": "sha512-CA3BatMyHkxZ48sgOCLdVHjFU36N7TF1HhqAHLFOkV6buwZnvMI84Cug8xD56B9mCuKrqXnLn94417GrZ/jjCQ==",
"license": "MIT",
"dependencies": {
- "@next/env": "15.1.2",
+ "@next/env": "15.3.2",
"@swc/counter": "0.1.3",
"@swc/helpers": "0.5.15",
"busboy": "1.6.0",
@@ -7858,15 +9285,15 @@
"node": "^18.18.0 || ^19.8.0 || >= 20.0.0"
},
"optionalDependencies": {
- "@next/swc-darwin-arm64": "15.1.2",
- "@next/swc-darwin-x64": "15.1.2",
- "@next/swc-linux-arm64-gnu": "15.1.2",
- "@next/swc-linux-arm64-musl": "15.1.2",
- "@next/swc-linux-x64-gnu": "15.1.2",
- "@next/swc-linux-x64-musl": "15.1.2",
- "@next/swc-win32-arm64-msvc": "15.1.2",
- "@next/swc-win32-x64-msvc": "15.1.2",
- "sharp": "^0.33.5"
+ "@next/swc-darwin-arm64": "15.3.2",
+ "@next/swc-darwin-x64": "15.3.2",
+ "@next/swc-linux-arm64-gnu": "15.3.2",
+ "@next/swc-linux-arm64-musl": "15.3.2",
+ "@next/swc-linux-x64-gnu": "15.3.2",
+ "@next/swc-linux-x64-musl": "15.3.2",
+ "@next/swc-win32-arm64-msvc": "15.3.2",
+ "@next/swc-win32-x64-msvc": "15.3.2",
+ "sharp": "^0.34.1"
},
"peerDependencies": {
"@opentelemetry/api": "^1.1.0",
@@ -7891,6 +9318,16 @@
}
}
},
+ "node_modules/next-themes": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz",
+ "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc"
+ }
+ },
"node_modules/next/node_modules/postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
@@ -7919,84 +9356,152 @@
"node": "^10 || ^12 || >=14"
}
},
- "node_modules/node-forge": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
- "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
- "dev": true,
- "license": "(BSD-3-Clause OR GPL-2.0)",
- "engines": {
- "node": ">= 6.13.0"
- }
- },
- "node_modules/node-ssh": {
- "version": "13.1.0",
- "resolved": "https://registry.npmjs.org/node-ssh/-/node-ssh-13.1.0.tgz",
- "integrity": "sha512-GLcw49yFd9+rUpP+FgX6wrF/N90cmuDl2n0i8d3L828b6riRjkb9w3SS+XvviRWbrAhLxuMKywFqxvQDZQ1bug==",
- "dev": true,
+ "node_modules/node-abi": {
+ "version": "3.75.0",
"license": "MIT",
"dependencies": {
- "@types/ssh2": "^1.11.9",
- "is-stream": "^2.0.0",
- "make-dir": "^3.1.0",
- "sb-promise-queue": "^2.1.0",
- "sb-scandir": "^3.1.0",
- "shell-escape": "^0.2.0",
- "ssh2": "^1.11.0"
+ "semver": "^7.3.5"
},
"engines": {
- "node": ">= 10"
+ "node": ">=10"
}
},
- "node_modules/normalize-package-data": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
- "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
- "dev": true,
- "license": "BSD-2-Clause",
+ "node_modules/node-addon-api": {
+ "version": "7.1.1",
+ "license": "MIT"
+ },
+ "node_modules/node-gyp": {
+ "version": "8.4.1",
+ "license": "MIT",
+ "optional": true,
"dependencies": {
- "hosted-git-info": "^4.0.1",
- "is-core-module": "^2.5.0",
- "semver": "^7.3.4",
- "validate-npm-package-license": "^3.0.1"
+ "env-paths": "^2.2.0",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.2.6",
+ "make-fetch-happen": "^9.1.0",
+ "nopt": "^5.0.0",
+ "npmlog": "^6.0.0",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.5",
+ "tar": "^6.1.2",
+ "which": "^2.0.2"
},
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/normalize-package-data/node_modules/semver": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
- "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
- "dev": true,
- "license": "ISC",
"bin": {
- "semver": "bin/semver.js"
+ "node-gyp": "bin/node-gyp.js"
},
"engines": {
- "node": ">=10"
+ "node": ">= 10.12.0"
}
},
- "node_modules/nwsapi": {
- "version": "2.2.19",
- "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.19.tgz",
- "integrity": "sha512-94bcyI3RsqiZufXjkr3ltkI86iEl+I7uiHVDtcq9wJUTwYQJ5odHDeSzkkrRzi80jJ8MaeZgqKjH1bAWAFw9bA==",
+ "node_modules/node-gyp-build": {
+ "version": "4.8.4",
+ "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
+ "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
+ "license": "MIT",
+ "bin": {
+ "node-gyp-build": "bin.js",
+ "node-gyp-build-optional": "optional.js",
+ "node-gyp-build-test": "build-test.js"
+ }
+ },
+ "node_modules/node-gyp/node_modules/rimraf": {
+ "version": "3.0.2",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.19",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
+ "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
"dev": true,
"license": "MIT"
},
- "node_modules/object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "node_modules/nopt": {
+ "version": "5.0.0",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "abbrev": "1"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
+ "node_modules/normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npmlog": {
+ "version": "6.0.2",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "are-we-there-yet": "^3.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^4.0.3",
+ "set-blocking": "^2.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/nwsapi": {
+ "version": "2.2.19",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-hash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/object-inspect": {
"version": "1.13.3",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
- "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -8037,15 +9542,16 @@
}
},
"node_modules/object.entries": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz",
- "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==",
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz",
+ "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
"define-properties": "^1.2.1",
- "es-object-atoms": "^1.0.0"
+ "es-object-atoms": "^1.1.1"
},
"engines": {
"node": ">= 0.4"
@@ -8104,17 +9610,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/ohash": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.4.tgz",
- "integrity": "sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==",
+ "node_modules/obuf": {
+ "version": "1.1.2",
"dev": true,
"license": "MIT"
},
"node_modules/on-finished": {
"version": "2.4.1",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
- "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
"license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
@@ -8125,9 +9627,6 @@
},
"node_modules/once": {
"version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
"license": "ISC",
"dependencies": {
"wrappy": "1"
@@ -8135,8 +9634,6 @@
},
"node_modules/one-time": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
- "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
"license": "MIT",
"dependencies": {
"fn.name": "1.x.x"
@@ -8160,6 +9657,24 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/own-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
+ "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.6",
+ "object-keys": "^1.1.1",
+ "safe-push-apply": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -8192,20 +9707,32 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true,
+ "node_modules/p-map": {
+ "version": "4.0.0",
"license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
"engines": {
- "node": ">=6"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0"
+ },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"callsites": "^3.0.0"
@@ -8214,24 +9741,31 @@
"node": ">=6"
}
},
- "node_modules/parse-json": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
- "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "node_modules/parse-entities": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz",
+ "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==",
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.0.0",
- "error-ex": "^1.3.1",
- "json-parse-even-better-errors": "^2.3.0",
- "lines-and-columns": "^1.1.6"
- },
- "engines": {
- "node": ">=8"
+ "@types/unist": "^2.0.0",
+ "character-entities-legacy": "^3.0.0",
+ "character-reference-invalid": "^2.0.0",
+ "decode-named-character-reference": "^1.0.0",
+ "is-alphanumerical": "^2.0.0",
+ "is-decimal": "^2.0.0",
+ "is-hexadecimal": "^2.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/parse-entities/node_modules/@types/unist": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
+ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
+ "license": "MIT"
+ },
"node_modules/parse-torrent-title": {
"version": "1.3.0",
"resolved": "git+ssh://git@github.com/TheBeastLT/parse-torrent-title.git#1169487e316a4eed898dcfd900957f89a253604c",
@@ -8245,10 +9779,10 @@
},
"node_modules/parse5": {
"version": "7.2.1",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
- "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"entities": "^4.5.0"
},
@@ -8258,8 +9792,6 @@
},
"node_modules/parseurl": {
"version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
@@ -8277,18 +9809,14 @@
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
"license": "MIT",
+ "optional": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/path-key": {
"version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -8299,44 +9827,150 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
"license": "MIT"
},
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/path-scurry/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
"node_modules/path-to-regexp": {
"version": "0.1.12",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
- "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
"license": "MIT"
},
- "node_modules/path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/pathe": {
"version": "1.1.2",
- "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
- "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
"dev": true,
"license": "MIT"
},
"node_modules/pathval": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz",
- "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 14.16"
}
},
+ "node_modules/pg": {
+ "version": "8.16.0",
+ "license": "MIT",
+ "dependencies": {
+ "pg-connection-string": "^2.9.0",
+ "pg-pool": "^3.10.0",
+ "pg-protocol": "^1.10.0",
+ "pg-types": "2.2.0",
+ "pgpass": "1.0.5"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ },
+ "optionalDependencies": {
+ "pg-cloudflare": "^1.2.5"
+ },
+ "peerDependencies": {
+ "pg-native": ">=3.0.1"
+ },
+ "peerDependenciesMeta": {
+ "pg-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/pg-cloudflare": {
+ "version": "1.2.5",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/pg-connection-string": {
+ "version": "2.9.0",
+ "license": "MIT"
+ },
+ "node_modules/pg-int8": {
+ "version": "1.0.1",
+ "license": "ISC",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/pg-numeric": {
+ "version": "1.0.2",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pg-pool": {
+ "version": "3.10.0",
+ "license": "MIT",
+ "peerDependencies": {
+ "pg": ">=8.0"
+ }
+ },
+ "node_modules/pg-protocol": {
+ "version": "1.10.0",
+ "license": "MIT"
+ },
+ "node_modules/pg-types": {
+ "version": "2.2.0",
+ "license": "MIT",
+ "dependencies": {
+ "pg-int8": "1.0.1",
+ "postgres-array": "~2.0.0",
+ "postgres-bytea": "~1.0.0",
+ "postgres-date": "~1.0.4",
+ "postgres-interval": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pgpass": {
+ "version": "1.0.5",
+ "license": "MIT",
+ "dependencies": {
+ "split2": "^4.1.0"
+ }
+ },
+ "node_modules/pgpass/node_modules/split2": {
+ "version": "4.2.0",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 10.x"
+ }
+ },
"node_modules/picocolors": {
"version": "1.1.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"license": "ISC"
},
"node_modules/picomatch": {
@@ -8362,22 +9996,20 @@
"node": ">=0.10.0"
}
},
- "node_modules/pkg-types": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.0.tgz",
- "integrity": "sha512-kS7yWjVFCkIw9hqdJBoMxDdzEngmkr5FXeWZZfQ6GoYacjVnsW6l2CcYW/0ThD0vF4LPJgVYnrg4d0uuhwYQbg==",
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "confbox": "^0.1.8",
- "mlly": "^1.7.3",
- "pathe": "^1.1.2"
+ "engines": {
+ "node": ">= 6"
}
},
"node_modules/possible-typed-array-names": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
- "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -8385,9 +10017,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.49",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
- "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
+ "version": "8.5.3",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
+ "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
"dev": true,
"funding": [
{
@@ -8405,7 +10037,7 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.7",
+ "nanoid": "^3.3.8",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -8413,6 +10045,221 @@
"node": "^10 || ^12 || >=14"
}
},
+ "node_modules/postcss-js": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
+ "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "camelcase-css": "^2.0.1"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
+ }
+ },
+ "node_modules/postcss-nested": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
+ "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "postcss-selector-parser": "^6.1.1"
+ },
+ "engines": {
+ "node": ">=12.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
+ "node_modules/postcss-nesting": {
+ "version": "13.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-13.0.1.tgz",
+ "integrity": "sha512-VbqqHkOBOt4Uu3G8Dm8n6lU5+9cJFxiuty9+4rcoyRPO9zZS1JIs6td49VIoix3qYqELHlJIn46Oih9SAKo+yQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT-0",
+ "dependencies": {
+ "@csstools/selector-resolve-nested": "^3.0.0",
+ "@csstools/selector-specificity": "^5.0.0",
+ "postcss-selector-parser": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-nesting/node_modules/@csstools/selector-resolve-nested": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-3.0.0.tgz",
+ "integrity": "sha512-ZoK24Yku6VJU1gS79a5PFmC8yn3wIapiKmPgun0hZgEI5AOqgH2kiPRsPz1qkGv4HL+wuDLH83yQyk6inMYrJQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT-0",
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "postcss-selector-parser": "^7.0.0"
+ }
+ },
+ "node_modules/postcss-nesting/node_modules/@csstools/selector-specificity": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz",
+ "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ }
+ ],
+ "license": "MIT-0",
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "postcss-selector-parser": "^7.0.0"
+ }
+ },
+ "node_modules/postcss-nesting/node_modules/postcss-selector-parser": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz",
+ "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/postgres-array": {
+ "version": "2.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postgres-bytea": {
+ "version": "1.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-date": {
+ "version": "1.0.7",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-interval": {
+ "version": "1.2.0",
+ "license": "MIT",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-range": {
+ "version": "1.1.4",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/prebuild-install": {
+ "version": "7.1.3",
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^2.0.0",
+ "node-abi": "^3.3.0",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ },
+ "bin": {
+ "prebuild-install": "bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -8425,8 +10272,6 @@
},
"node_modules/prettier": {
"version": "3.4.2",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
- "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
"dev": true,
"license": "MIT",
"bin": {
@@ -8439,24 +10284,28 @@
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
- "node_modules/printable-characters": {
- "version": "1.0.42",
- "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz",
- "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==",
- "dev": true,
- "license": "Unlicense"
+ "node_modules/promise-inflight": {
+ "version": "1.0.1",
+ "license": "ISC",
+ "optional": true
},
- "node_modules/process-nextick-args": {
+ "node_modules/promise-retry": {
"version": "2.0.1",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
- "dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "err-code": "^2.0.2",
+ "retry": "^0.12.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
},
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.4.0",
@@ -8464,10 +10313,18 @@
"react-is": "^16.13.1"
}
},
+ "node_modules/property-information": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz",
+ "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/proxy-addr": {
"version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
"license": "MIT",
"dependencies": {
"forwarded": "0.2.0",
@@ -8477,10 +10334,22 @@
"node": ">= 0.10"
}
},
+ "node_modules/proxy-compare": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-3.0.1.tgz",
+ "integrity": "sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q==",
+ "license": "MIT"
+ },
+ "node_modules/pump": {
+ "version": "3.0.2",
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
"node_modules/punycode": {
"version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
- "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -8489,8 +10358,6 @@
},
"node_modules/qs": {
"version": "6.13.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
- "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.0.6"
@@ -8523,20 +10390,8 @@
],
"license": "MIT"
},
- "node_modules/quick-lru": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
- "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/range-parser": {
"version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
@@ -8544,8 +10399,6 @@
},
"node_modules/raw-body": {
"version": "2.5.2",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
- "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
@@ -8557,242 +10410,164 @@
"node": ">= 0.8"
}
},
+ "node_modules/rc": {
+ "version": "1.2.8",
+ "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
"node_modules/react": {
- "version": "19.0.0",
- "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz",
- "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==",
+ "version": "19.1.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
+ "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
- "version": "19.0.0",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz",
- "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==",
+ "version": "19.1.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
+ "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
"license": "MIT",
"dependencies": {
- "scheduler": "^0.25.0"
+ "scheduler": "^0.26.0"
},
"peerDependencies": {
- "react": "^19.0.0"
+ "react": "^19.1.0"
+ }
+ },
+ "node_modules/react-icons": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
+ "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "*"
}
},
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "dev": true,
"license": "MIT"
},
- "node_modules/react-select": {
- "version": "5.9.0",
- "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.9.0.tgz",
- "integrity": "sha512-nwRKGanVHGjdccsnzhFte/PULziueZxGD8LL2WojON78Mvnq7LdAMEtu2frrwld1fr3geixg3iiMBIc/LLAZpw==",
+ "node_modules/react-markdown": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz",
+ "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==",
"license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.12.0",
- "@emotion/cache": "^11.4.0",
- "@emotion/react": "^11.8.1",
- "@floating-ui/dom": "^1.0.1",
- "@types/react-transition-group": "^4.4.0",
- "memoize-one": "^6.0.0",
- "prop-types": "^15.6.0",
- "react-transition-group": "^4.3.0",
- "use-isomorphic-layout-effect": "^1.2.0"
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "devlop": "^1.0.0",
+ "hast-util-to-jsx-runtime": "^2.0.0",
+ "html-url-attributes": "^3.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "remark-parse": "^11.0.0",
+ "remark-rehype": "^11.0.0",
+ "unified": "^11.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
},
"peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
- "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ "@types/react": ">=18",
+ "react": ">=18"
}
},
- "node_modules/react-toastify": {
- "version": "11.0.2",
- "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.2.tgz",
- "integrity": "sha512-GjHuGaiXMvbls3ywqv8XdWONwrcO4DXCJIY1zVLkHU73gEElKvTTXNI5Vom3s/k/M8hnkrfsqgBSX3OwmlonbA==",
+ "node_modules/react-remove-scroll": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.0.tgz",
+ "integrity": "sha512-sGsQtcjMqdQyijAHytfGEELB8FufGbfXIsvUTe+NLx1GDRJCXtCFLBLUI1eyZCKXXvbEU2C6gai0PZKoIE9Vbg==",
"license": "MIT",
"dependencies": {
- "clsx": "^2.1.1"
+ "react-remove-scroll-bar": "^2.3.7",
+ "react-style-singleton": "^2.2.3",
+ "tslib": "^2.1.0",
+ "use-callback-ref": "^1.3.3",
+ "use-sidecar": "^1.1.3"
+ },
+ "engines": {
+ "node": ">=10"
},
"peerDependencies": {
- "react": "^18 || ^19",
- "react-dom": "^18 || ^19"
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
- "node_modules/react-transition-group": {
- "version": "4.4.5",
- "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
- "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
- "license": "BSD-3-Clause",
+ "node_modules/react-remove-scroll-bar": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
+ "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
+ "license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.5.5",
- "dom-helpers": "^5.0.1",
- "loose-envify": "^1.4.0",
- "prop-types": "^15.6.2"
+ "react-style-singleton": "^2.2.2",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
},
"peerDependencies": {
- "react": ">=16.6.0",
- "react-dom": ">=16.6.0"
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
- "node_modules/read-pkg": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
- "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==",
- "dev": true,
+ "node_modules/react-style-singleton": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
+ "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
"license": "MIT",
"dependencies": {
- "load-json-file": "^4.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^3.0.0"
+ "get-nonce": "^1.0.0",
+ "tslib": "^2.0.0"
},
"engines": {
- "node": ">=4"
- }
- },
- "node_modules/read-pkg-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz",
- "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "find-up": "^2.0.0",
- "read-pkg": "^3.0.0"
+ "node": ">=10"
},
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/read-pkg-up/node_modules/find-up": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
- "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "locate-path": "^2.0.0"
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
},
- "engines": {
- "node": ">=4"
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
}
},
- "node_modules/read-pkg-up/node_modules/locate-path": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
- "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-locate": "^2.0.0",
- "path-exists": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/read-pkg-up/node_modules/p-limit": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
- "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-try": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/read-pkg-up/node_modules/p-locate": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
- "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-limit": "^1.1.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/read-pkg-up/node_modules/p-try": {
+ "node_modules/read-cache": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
- "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/read-pkg-up/node_modules/path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/read-pkg/node_modules/hosted-git-info": {
- "version": "2.8.9",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
- "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/read-pkg/node_modules/normalize-package-data": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
- "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "hosted-git-info": "^2.1.4",
- "resolve": "^1.10.0",
- "semver": "2 || 3 || 4 || 5",
- "validate-npm-package-license": "^3.0.1"
- }
- },
- "node_modules/read-pkg/node_modules/path-type": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
- "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "pify": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/read-pkg/node_modules/pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/read-pkg/node_modules/semver": {
- "version": "5.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
- "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver"
+ "pify": "^2.3.0"
}
},
"node_modules/readable-stream": {
"version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
@@ -8804,47 +10579,32 @@
}
},
"node_modules/readdirp": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
- "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 14.16.0"
- },
- "funding": {
- "type": "individual",
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/redent": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
- "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "indent-string": "^4.0.0",
- "strip-indent": "^3.0.0"
+ "picomatch": "^2.2.1"
},
"engines": {
- "node": ">=8"
+ "node": ">=8.10.0"
}
},
"node_modules/reflect.getprototypeof": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz",
- "integrity": "sha512-r0Ay04Snci87djAsI4U+WNRcSw5S4pOH7qFjd/veA5gC7TbqESR3tcj28ia95L/fYUDw11JKP7uqUKUAfVvV5Q==",
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
+ "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"define-properties": "^1.2.1",
- "dunder-proto": "^1.0.1",
- "es-abstract": "^1.23.6",
+ "es-abstract": "^1.23.9",
"es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "gopd": "^1.2.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.7",
+ "get-proto": "^1.0.1",
"which-builtin-type": "^1.2.1"
},
"engines": {
@@ -8854,22 +10614,18 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/regenerator-runtime": {
- "version": "0.14.1",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
- "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
- "license": "MIT"
- },
"node_modules/regexp.prototype.flags": {
- "version": "1.5.3",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz",
- "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==",
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
+ "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.7",
+ "call-bind": "^1.0.8",
"define-properties": "^1.2.1",
"es-errors": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
"set-function-name": "^2.0.2"
},
"engines": {
@@ -8879,20 +10635,44 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
+ "node_modules/remark-parse": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
+ "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==",
"license": "MIT",
- "engines": {
- "node": ">=0.10.0"
+ "dependencies": {
+ "@types/mdast": "^4.0.0",
+ "mdast-util-from-markdown": "^2.0.0",
+ "micromark-util-types": "^2.0.0",
+ "unified": "^11.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/remark-rehype": {
+ "version": "11.1.2",
+ "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz",
+ "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "unified": "^11.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
"node_modules/resolve": {
"version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"is-core-module": "^2.16.0",
@@ -8913,6 +10693,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
@@ -8920,18 +10701,24 @@
},
"node_modules/resolve-pkg-maps": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
- "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
}
},
+ "node_modules/retry": {
+ "version": "0.12.0",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
"node_modules/reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -8939,24 +10726,8 @@
"node": ">=0.10.0"
}
},
- "node_modules/rimraf": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
- "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- }
- },
"node_modules/rollup": {
"version": "4.29.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.29.1.tgz",
- "integrity": "sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -8992,69 +10763,12 @@
"fsevents": "~2.3.2"
}
},
- "node_modules/rollup-plugin-inject": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz",
- "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==",
- "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "estree-walker": "^0.6.1",
- "magic-string": "^0.25.3",
- "rollup-pluginutils": "^2.8.1"
- }
- },
- "node_modules/rollup-plugin-inject/node_modules/estree-walker": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
- "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/rollup-plugin-inject/node_modules/magic-string": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
- "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "sourcemap-codec": "^1.4.8"
- }
- },
- "node_modules/rollup-plugin-node-polyfills": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz",
- "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "rollup-plugin-inject": "^3.0.0"
- }
- },
- "node_modules/rollup-pluginutils": {
- "version": "2.8.2",
- "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
- "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "estree-walker": "^0.6.1"
- }
- },
- "node_modules/rollup-pluginutils/node_modules/estree-walker": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
- "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/rrweb-cssom": {
"version": "0.7.1",
- "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz",
- "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/run-parallel": {
"version": "1.2.0",
@@ -9102,8 +10816,6 @@
},
"node_modules/safe-buffer": {
"version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"funding": [
{
"type": "github",
@@ -9120,6 +10832,23 @@
],
"license": "MIT"
},
+ "node_modules/safe-push-apply": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
+ "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/safe-regex-test": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
@@ -9140,8 +10869,6 @@
},
"node_modules/safe-stable-stringify": {
"version": "2.5.0",
- "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
- "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
"license": "MIT",
"engines": {
"node": ">=10"
@@ -9149,16 +10876,14 @@
},
"node_modules/safer-buffer": {
"version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/saxes": {
"version": "6.0.0",
- "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
- "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
"dev": true,
"license": "ISC",
+ "optional": true,
+ "peer": true,
"dependencies": {
"xmlchars": "^2.2.0"
},
@@ -9166,63 +10891,26 @@
"node": ">=v12.22.7"
}
},
- "node_modules/sb-promise-queue": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/sb-promise-queue/-/sb-promise-queue-2.1.0.tgz",
- "integrity": "sha512-zwq4YuP1FQFkGx2Q7GIkZYZ6PqWpV+bg0nIO1sJhWOyGyhqbj0MsTvK6lCFo5TQwX5pZr6SCQ75e8PCDCuNvkg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/sb-scandir": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/sb-scandir/-/sb-scandir-3.1.0.tgz",
- "integrity": "sha512-70BVm2xz9jn94zSQdpvYrEG101/UV9TVGcfWr9T5iob3QhCK4lYXeculfBqPGFv3XTeKgx4dpWyYIDeZUqo4kg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "sb-promise-queue": "^2.1.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/scheduler": {
- "version": "0.25.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz",
- "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==",
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
+ "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
"license": "MIT"
},
- "node_modules/selfsigned": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz",
- "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node-forge": "^1.3.0",
- "node-forge": "^1"
+ "node_modules/semver": {
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
- "node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
"node_modules/send": {
"version": "0.19.0",
- "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
- "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
"license": "MIT",
"dependencies": {
"debug": "2.6.9",
@@ -9245,8 +10933,6 @@
},
"node_modules/send/node_modules/debug": {
"version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
@@ -9254,14 +10940,10 @@
},
"node_modules/send/node_modules/debug/node_modules/ms": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/send/node_modules/encodeurl": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
@@ -9269,8 +10951,6 @@
},
"node_modules/serve-static": {
"version": "1.16.2",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
- "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
"license": "MIT",
"dependencies": {
"encodeurl": "~2.0.0",
@@ -9282,6 +10962,11 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "license": "ISC",
+ "optional": true
+ },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -9316,23 +11001,36 @@
"node": ">= 0.4"
}
},
+ "node_modules/set-proto": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
+ "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/setprototypeof": {
"version": "1.2.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"license": "ISC"
},
"node_modules/sharp": {
- "version": "0.33.5",
- "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz",
- "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==",
+ "version": "0.34.1",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.1.tgz",
+ "integrity": "sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==",
"hasInstallScript": true,
"license": "Apache-2.0",
"optional": true,
"dependencies": {
"color": "^4.2.3",
"detect-libc": "^2.0.3",
- "semver": "^7.6.3"
+ "semver": "^7.7.1"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
@@ -9341,44 +11039,30 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-darwin-arm64": "0.33.5",
- "@img/sharp-darwin-x64": "0.33.5",
- "@img/sharp-libvips-darwin-arm64": "1.0.4",
- "@img/sharp-libvips-darwin-x64": "1.0.4",
- "@img/sharp-libvips-linux-arm": "1.0.5",
- "@img/sharp-libvips-linux-arm64": "1.0.4",
- "@img/sharp-libvips-linux-s390x": "1.0.4",
- "@img/sharp-libvips-linux-x64": "1.0.4",
- "@img/sharp-libvips-linuxmusl-arm64": "1.0.4",
- "@img/sharp-libvips-linuxmusl-x64": "1.0.4",
- "@img/sharp-linux-arm": "0.33.5",
- "@img/sharp-linux-arm64": "0.33.5",
- "@img/sharp-linux-s390x": "0.33.5",
- "@img/sharp-linux-x64": "0.33.5",
- "@img/sharp-linuxmusl-arm64": "0.33.5",
- "@img/sharp-linuxmusl-x64": "0.33.5",
- "@img/sharp-wasm32": "0.33.5",
- "@img/sharp-win32-ia32": "0.33.5",
- "@img/sharp-win32-x64": "0.33.5"
- }
- },
- "node_modules/sharp/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "license": "ISC",
- "optional": true,
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
+ "@img/sharp-darwin-arm64": "0.34.1",
+ "@img/sharp-darwin-x64": "0.34.1",
+ "@img/sharp-libvips-darwin-arm64": "1.1.0",
+ "@img/sharp-libvips-darwin-x64": "1.1.0",
+ "@img/sharp-libvips-linux-arm": "1.1.0",
+ "@img/sharp-libvips-linux-arm64": "1.1.0",
+ "@img/sharp-libvips-linux-ppc64": "1.1.0",
+ "@img/sharp-libvips-linux-s390x": "1.1.0",
+ "@img/sharp-libvips-linux-x64": "1.1.0",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.1.0",
+ "@img/sharp-libvips-linuxmusl-x64": "1.1.0",
+ "@img/sharp-linux-arm": "0.34.1",
+ "@img/sharp-linux-arm64": "0.34.1",
+ "@img/sharp-linux-s390x": "0.34.1",
+ "@img/sharp-linux-x64": "0.34.1",
+ "@img/sharp-linuxmusl-arm64": "0.34.1",
+ "@img/sharp-linuxmusl-x64": "0.34.1",
+ "@img/sharp-wasm32": "0.34.1",
+ "@img/sharp-win32-ia32": "0.34.1",
+ "@img/sharp-win32-x64": "0.34.1"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -9390,25 +11074,14 @@
},
"node_modules/shebang-regex": {
"version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
- "node_modules/shell-escape": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/shell-escape/-/shell-escape-0.2.0.tgz",
- "integrity": "sha512-uRRBT2MfEOyxuECseCZd28jC1AJ8hmqqneWQ4VWUTgCAFvb3wKU1jLqj6egC4Exrr88ogg3dp+zroH4wJuaXzw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/side-channel": {
"version": "1.1.0",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
- "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -9426,8 +11099,6 @@
},
"node_modules/side-channel-list": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
- "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -9442,8 +11113,6 @@
},
"node_modules/side-channel-map": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
- "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -9460,8 +11129,6 @@
},
"node_modules/side-channel-weakmap": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
- "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -9479,135 +11146,186 @@
},
"node_modules/siginfo": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
- "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
"dev": true,
"license": "ISC"
},
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/simple-get": {
+ "version": "4.0.1",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
"node_modules/simple-swizzle": {
"version": "0.2.2",
- "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
- "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"license": "MIT",
"dependencies": {
"is-arrayish": "^0.3.1"
}
},
- "node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "license": "BSD-3-Clause",
+ "node_modules/smart-buffer": {
+ "version": "4.2.0",
+ "license": "MIT",
+ "optional": true,
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks": {
+ "version": "2.8.4",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "ip-address": "^9.0.5",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks-proxy-agent": {
+ "version": "6.2.1",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "agent-base": "^6.0.2",
+ "debug": "^4.3.3",
+ "socks": "^2.6.2"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/socks-proxy-agent/node_modules/agent-base": {
+ "version": "6.0.2",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/sonner": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.3.tgz",
+ "integrity": "sha512-njQ4Hht92m0sMqqHVDL32V2Oun9W1+PHO9NDv9FHfJjT3JT22IG4Jpo3FPQy+mouRKCXFWO+r67v6MrHX2zeIA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc",
+ "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/sourcemap-codec": {
- "version": "1.4.8",
- "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
- "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
- "deprecated": "Please use @jridgewell/sourcemap-codec instead",
- "dev": true,
+ "node_modules/space-separated-tokens": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
+ "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.1.3",
+ "license": "BSD-3-Clause",
+ "optional": true
+ },
+ "node_modules/sqlite": {
+ "version": "5.1.1",
"license": "MIT"
},
- "node_modules/spdx-correct": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
- "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "spdx-expression-parse": "^3.0.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "node_modules/spdx-exceptions": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
- "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
- "dev": true,
- "license": "CC-BY-3.0"
- },
- "node_modules/spdx-expression-parse": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
- "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "spdx-exceptions": "^2.1.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "node_modules/spdx-license-ids": {
- "version": "3.0.21",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz",
- "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==",
- "dev": true,
- "license": "CC0-1.0"
- },
- "node_modules/split": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
- "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "through": "2"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/split2": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
- "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "readable-stream": "^3.0.0"
- }
- },
- "node_modules/ssh2": {
- "version": "1.16.0",
- "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.16.0.tgz",
- "integrity": "sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg==",
- "dev": true,
+ "node_modules/sqlite3": {
+ "version": "5.1.7",
"hasInstallScript": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "asn1": "^0.2.6",
- "bcrypt-pbkdf": "^1.0.2"
- },
- "engines": {
- "node": ">=10.16.0"
+ "bindings": "^1.5.0",
+ "node-addon-api": "^7.0.0",
+ "prebuild-install": "^7.1.1",
+ "tar": "^6.1.11"
},
"optionalDependencies": {
- "cpu-features": "~0.0.10",
- "nan": "^2.20.0"
+ "node-gyp": "8.x"
+ },
+ "peerDependencies": {
+ "node-gyp": "8.x"
+ },
+ "peerDependenciesMeta": {
+ "node-gyp": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ssri": {
+ "version": "8.0.1",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.1.1"
+ },
+ "engines": {
+ "node": ">= 8"
}
},
"node_modules/stable-hash": {
- "version": "0.0.4",
- "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz",
- "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==",
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz",
+ "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==",
"dev": true,
"license": "MIT"
},
"node_modules/stack-trace": {
"version": "0.0.10",
- "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
- "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
"license": "MIT",
"engines": {
"node": "*"
@@ -9615,26 +11333,11 @@
},
"node_modules/stackback": {
"version": "0.0.2",
- "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
- "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
"dev": true,
"license": "MIT"
},
- "node_modules/stacktracey": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz",
- "integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==",
- "dev": true,
- "license": "Unlicense",
- "dependencies": {
- "as-table": "^1.0.36",
- "get-source": "^2.0.12"
- }
- },
"node_modules/statuses": {
"version": "2.0.1",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
- "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
@@ -9642,22 +11345,9 @@
},
"node_modules/std-env": {
"version": "3.8.0",
- "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz",
- "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==",
"dev": true,
"license": "MIT"
},
- "node_modules/stoppable": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz",
- "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4",
- "npm": ">=6"
- }
- },
"node_modules/streamsearch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
@@ -9668,14 +11358,26 @@
},
"node_modules/string_decoder": {
"version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/string-width": {
+ "version": "4.2.3",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
@@ -9690,13 +11392,18 @@
"node": ">=8"
}
},
- "node_modules/string-width/node_modules/emoji-regex": {
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true,
"license": "MIT"
},
+ "node_modules/string-width/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "devOptional": true,
+ "license": "MIT"
+ },
"node_modules/string.prototype.includes": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
@@ -9810,7 +11517,33 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/stringify-entities": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
+ "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
+ "license": "MIT",
+ "dependencies": {
+ "character-entities-html4": "^2.0.0",
+ "character-entities-legacy": "^3.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
@@ -9833,30 +11566,29 @@
"node": ">=4"
}
},
- "node_modules/strip-indent": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
- "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
- "dev": true,
+ "node_modules/strip-json-comments": {
+ "version": "2.0.1",
"license": "MIT",
- "dependencies": {
- "min-indent": "^1.0.0"
- },
"engines": {
- "node": ">=8"
+ "node": ">=0.10.0"
}
},
- "node_modules/strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true,
+ "node_modules/style-to-js": {
+ "version": "1.1.16",
+ "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.16.tgz",
+ "integrity": "sha512-/Q6ld50hKYPH3d/r6nr117TZkHR0w0kGGIVfpG9N6D8NymRPM9RqCUv4pRpJ62E5DqOYx2AFpbZMyCPnjQCnOw==",
"license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "dependencies": {
+ "style-to-object": "1.0.8"
+ }
+ },
+ "node_modules/style-to-object": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz",
+ "integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==",
+ "license": "MIT",
+ "dependencies": {
+ "inline-style-parser": "0.2.4"
}
},
"node_modules/styled-jsx": {
@@ -9882,16 +11614,88 @@
}
}
},
- "node_modules/stylis": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
- "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==",
- "license": "MIT"
+ "node_modules/sucrase": {
+ "version": "3.35.0",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
+ "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "glob": "^10.3.10",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/sucrase/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/sucrase/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/sucrase/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/sucrase/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
},
"node_modules/super-regex": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/super-regex/-/super-regex-1.0.0.tgz",
- "integrity": "sha512-CY8u7DtbvucKuquCmOFEKhr9Besln7n9uN8eFbwcoGYWXOMW07u2o8njWaiXt11ylS3qoGF55pILjRmPlbodyg==",
"license": "MIT",
"dependencies": {
"function-timeout": "^1.0.1",
@@ -9921,6 +11725,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -9931,11 +11736,48 @@
},
"node_modules/symbol-tree": {
"version": "3.2.4",
- "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
- "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
"dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
+ },
+ "node_modules/tabbable": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
+ "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
"license": "MIT"
},
+ "node_modules/tailwind-merge": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.0.tgz",
+ "integrity": "sha512-fyW/pEfcQSiigd5SNn0nApUOxx0zB/dm6UDU/rEwc2c3sX2smWUNbapHv+QRqLGVp9GWX3THIa7MUGPo+YkDzQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
+ "node_modules/tailwind-scrollbar-hide": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/tailwind-scrollbar-hide/-/tailwind-scrollbar-hide-1.1.7.tgz",
+ "integrity": "sha512-X324n9OtpTmOMqEgDUEA/RgLrNfBF/jwJdctaPZDzB3mppxJk7TLIDmOreEDm1Bq4R9LSPu4Epf8VSdovNU+iA==",
+ "license": "MIT"
+ },
+ "node_modules/tailwindcss": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.7.tgz",
+ "integrity": "sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==",
+ "license": "MIT"
+ },
+ "node_modules/tailwindcss-animate": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
+ "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "tailwindcss": ">=3.0.0 || insiders"
+ }
+ },
"node_modules/tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
@@ -9946,84 +11788,85 @@
"node": ">=6"
}
},
- "node_modules/text-extensions": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz",
- "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==",
- "dev": true,
- "license": "MIT",
+ "node_modules/tar": {
+ "version": "6.2.1",
+ "license": "ISC",
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
"engines": {
- "node": ">=0.10"
+ "node": ">=10"
+ }
+ },
+ "node_modules/tar-fs": {
+ "version": "2.1.2",
+ "license": "MIT",
+ "dependencies": {
+ "chownr": "^1.1.1",
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.1.4"
+ }
+ },
+ "node_modules/tar-fs/node_modules/chownr": {
+ "version": "1.1.4",
+ "license": "ISC"
+ },
+ "node_modules/tar-stream": {
+ "version": "2.2.0",
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tar/node_modules/minipass": {
+ "version": "5.0.0",
+ "license": "ISC",
+ "engines": {
+ "node": ">=8"
}
},
"node_modules/text-hex": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
- "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==",
"license": "MIT"
},
- "node_modules/through": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/through2": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
- "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "readable-stream": "~2.3.6",
- "xtend": "~4.0.1"
+ "any-promise": "^1.0.0"
}
},
- "node_modules/through2/node_modules/isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/through2/node_modules/readable-stream": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
- "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "node_modules/through2/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/through2/node_modules/string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "~5.1.0"
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
}
},
"node_modules/time-span": {
"version": "5.1.0",
- "resolved": "https://registry.npmjs.org/time-span/-/time-span-5.1.0.tgz",
- "integrity": "sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==",
"license": "MIT",
"dependencies": {
"convert-hrtime": "^5.0.0"
@@ -10037,22 +11880,61 @@
},
"node_modules/tinybench": {
"version": "2.9.0",
- "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
- "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
"dev": true,
"license": "MIT"
},
"node_modules/tinyexec": {
"version": "0.3.1",
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz",
- "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==",
"dev": true,
"license": "MIT"
},
+ "node_modules/tinyglobby": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
+ "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyglobby/node_modules/fdir": {
+ "version": "6.4.4",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz",
+ "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tinyglobby/node_modules/picomatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
+ "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/tinypool": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz",
- "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -10061,8 +11943,6 @@
},
"node_modules/tinyrainbow": {
"version": "1.2.0",
- "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz",
- "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -10071,8 +11951,6 @@
},
"node_modules/tinyspy": {
"version": "3.0.2",
- "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz",
- "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -10081,10 +11959,10 @@
},
"node_modules/tldts": {
"version": "6.1.84",
- "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.84.tgz",
- "integrity": "sha512-aRGIbCIF3teodtUFAYSdQONVmDRy21REM3o6JnqWn5ZkQBJJ4gHxhw6OfwQ+WkSAi3ASamrS4N4nyazWx6uTYg==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"tldts-core": "^6.1.84"
},
@@ -10094,10 +11972,10 @@
},
"node_modules/tldts-core": {
"version": "6.1.84",
- "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.84.tgz",
- "integrity": "sha512-NaQa1W76W2aCGjXybvnMYzGSM4x8fvG2AN/pla7qxcg0ZHbooOPhA8kctmOZUDfZyhDL27OGNbwAeig8P4p1vg==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/to-regex-range": {
"version": "5.0.1",
@@ -10114,8 +11992,6 @@
},
"node_modules/toidentifier": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
- "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"license": "MIT",
"engines": {
"node": ">=0.6"
@@ -10123,10 +11999,10 @@
},
"node_modules/tough-cookie": {
"version": "5.1.2",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz",
- "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==",
"dev": true,
"license": "BSD-3-Clause",
+ "optional": true,
+ "peer": true,
"dependencies": {
"tldts": "^6.1.32"
},
@@ -10136,10 +12012,10 @@
},
"node_modules/tr46": {
"version": "5.1.0",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.0.tgz",
- "integrity": "sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"punycode": "^2.3.1"
},
@@ -10147,36 +12023,95 @@
"node": ">=18"
}
},
- "node_modules/trim-newlines": {
+ "node_modules/trim-lines": {
"version": "3.0.1",
- "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
- "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
- "dev": true,
+ "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
+ "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
"license": "MIT",
- "engines": {
- "node": ">=8"
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/triple-beam": {
"version": "1.4.1",
- "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
- "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
"license": "MIT",
"engines": {
"node": ">= 14.0.0"
}
},
+ "node_modules/trough": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz",
+ "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/ts-api-utils": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
- "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
+ "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=16"
+ "node": ">=18.12"
},
"peerDependencies": {
- "typescript": ">=4.2.0"
+ "typescript": ">=4.8.4"
+ }
+ },
+ "node_modules/ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/ts-node": {
+ "version": "10.9.2",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
+ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cspotcode/source-map-support": "^0.8.0",
+ "@tsconfig/node10": "^1.0.7",
+ "@tsconfig/node12": "^1.0.7",
+ "@tsconfig/node14": "^1.0.0",
+ "@tsconfig/node16": "^1.0.2",
+ "acorn": "^8.4.1",
+ "acorn-walk": "^8.1.1",
+ "arg": "^4.1.0",
+ "create-require": "^1.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "v8-compile-cache-lib": "^3.0.1",
+ "yn": "3.1.1"
+ },
+ "bin": {
+ "ts-node": "dist/bin.js",
+ "ts-node-cwd": "dist/bin-cwd.js",
+ "ts-node-esm": "dist/bin-esm.js",
+ "ts-node-script": "dist/bin-script.js",
+ "ts-node-transpile-only": "dist/bin-transpile.js",
+ "ts-script": "dist/bin-script-deprecated.js"
+ },
+ "peerDependencies": {
+ "@swc/core": ">=1.2.50",
+ "@swc/wasm": ">=1.2.50",
+ "@types/node": "*",
+ "typescript": ">=2.7"
+ },
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "@swc/wasm": {
+ "optional": true
+ }
}
},
"node_modules/tsconfig-paths": {
@@ -10200,8 +12135,6 @@
},
"node_modules/tsx": {
"version": "4.19.2",
- "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz",
- "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10218,12 +12151,15 @@
"fsevents": "~2.3.3"
}
},
- "node_modules/tweetnacl": {
- "version": "0.14.5",
- "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
- "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
- "dev": true,
- "license": "Unlicense"
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
},
"node_modules/type-check": {
"version": "0.4.0",
@@ -10238,23 +12174,8 @@
"node": ">= 0.8.0"
}
},
- "node_modules/type-fest": {
- "version": "0.18.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz",
- "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/type-is": {
"version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"license": "MIT",
"dependencies": {
"media-typer": "0.3.0",
@@ -10342,17 +12263,8 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/typedarray": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/typescript": {
"version": "5.7.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz",
- "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -10363,27 +12275,6 @@
"node": ">=14.17"
}
},
- "node_modules/ufo": {
- "version": "1.5.4",
- "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",
- "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/uglify-js": {
- "version": "3.19.3",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
- "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
- "dev": true,
- "license": "BSD-2-Clause",
- "optional": true,
- "bin": {
- "uglifyjs": "bin/uglifyjs"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/unbox-primitive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
@@ -10405,8 +12296,6 @@
},
"node_modules/undici": {
"version": "7.2.3",
- "resolved": "https://registry.npmjs.org/undici/-/undici-7.2.3.tgz",
- "integrity": "sha512-2oSLHaDalSt2/O/wHA9M+/ZPAOcU2yrSP/cdBYJ+YxZskiPYDSqHbysLSlD7gq3JMqOoJI5O31RVU3BxX/MnAA==",
"license": "MIT",
"engines": {
"node": ">=20.18.1"
@@ -10414,35 +12303,183 @@
},
"node_modules/undici-types": {
"version": "6.19.8",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
- "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"dev": true,
"license": "MIT"
},
- "node_modules/unenv": {
- "name": "unenv-nightly",
- "version": "2.0.0-20241218-183400-5d6aec3",
- "resolved": "https://registry.npmjs.org/unenv-nightly/-/unenv-nightly-2.0.0-20241218-183400-5d6aec3.tgz",
- "integrity": "sha512-7Xpi29CJRbOV1/IrC03DawMJ0hloklDLq/cigSe+J2jkcC+iDres2Cy0r4ltj5f0x7DqsaGaB4/dLuCPPFZnZA==",
- "dev": true,
+ "node_modules/unified": {
+ "version": "11.0.5",
+ "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
+ "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==",
"license": "MIT",
"dependencies": {
- "defu": "^6.1.4",
- "mlly": "^1.7.3",
- "ohash": "^1.1.4",
- "pathe": "^1.1.2",
- "ufo": "^1.5.4"
+ "@types/unist": "^3.0.0",
+ "bail": "^2.0.0",
+ "devlop": "^1.0.0",
+ "extend": "^3.0.0",
+ "is-plain-obj": "^4.0.0",
+ "trough": "^2.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unique-filename": {
+ "version": "1.1.1",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "node_modules/unique-slug": {
+ "version": "2.0.2",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "node_modules/unist-util-is": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz",
+ "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
+ "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-stringify-position": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
+ "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz",
+ "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz",
+ "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
}
},
"node_modules/unpipe": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
+ "node_modules/unrs-resolver": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.2.tgz",
+ "integrity": "sha512-BBKpaylOW8KbHsu378Zky/dGh4ckT/4NW/0SHRABdqRLcQJ2dAOjDo9g97p04sWflm0kqPqpUatxReNV/dqI5A==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "napi-postinstall": "^0.2.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/JounQin"
+ },
+ "optionalDependencies": {
+ "@unrs/resolver-binding-darwin-arm64": "1.7.2",
+ "@unrs/resolver-binding-darwin-x64": "1.7.2",
+ "@unrs/resolver-binding-freebsd-x64": "1.7.2",
+ "@unrs/resolver-binding-linux-arm-gnueabihf": "1.7.2",
+ "@unrs/resolver-binding-linux-arm-musleabihf": "1.7.2",
+ "@unrs/resolver-binding-linux-arm64-gnu": "1.7.2",
+ "@unrs/resolver-binding-linux-arm64-musl": "1.7.2",
+ "@unrs/resolver-binding-linux-ppc64-gnu": "1.7.2",
+ "@unrs/resolver-binding-linux-riscv64-gnu": "1.7.2",
+ "@unrs/resolver-binding-linux-riscv64-musl": "1.7.2",
+ "@unrs/resolver-binding-linux-s390x-gnu": "1.7.2",
+ "@unrs/resolver-binding-linux-x64-gnu": "1.7.2",
+ "@unrs/resolver-binding-linux-x64-musl": "1.7.2",
+ "@unrs/resolver-binding-wasm32-wasi": "1.7.2",
+ "@unrs/resolver-binding-win32-arm64-msvc": "1.7.2",
+ "@unrs/resolver-binding-win32-ia32-msvc": "1.7.2",
+ "@unrs/resolver-binding-win32-x64-msvc": "1.7.2"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
+ "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -10453,13 +12490,20 @@
"punycode": "^2.1.0"
}
},
- "node_modules/use-isomorphic-layout-effect": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz",
- "integrity": "sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==",
+ "node_modules/use-callback-ref": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
+ "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
"license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
"peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
@@ -10467,45 +12511,92 @@
}
}
},
+ "node_modules/use-sidecar": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
+ "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
+ "license": "MIT",
+ "dependencies": {
+ "detect-node-es": "^1.1.0",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
+ "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT"
},
"node_modules/utils-merge": {
"version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
"license": "MIT",
"engines": {
"node": ">= 0.4.0"
}
},
- "node_modules/validate-npm-package-license": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
- "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "node_modules/v8-compile-cache-lib": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "spdx-correct": "^3.0.0",
- "spdx-expression-parse": "^3.0.0"
- }
+ "license": "MIT"
},
"node_modules/vary": {
"version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
+ "node_modules/vfile": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
+ "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-message": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz",
+ "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-stringify-position": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/vite": {
"version": "5.4.11",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz",
- "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10564,8 +12655,6 @@
},
"node_modules/vite-node": {
"version": "2.1.8",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.8.tgz",
- "integrity": "sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10585,384 +12674,8 @@
"url": "https://opencollective.com/vitest"
}
},
- "node_modules/vite/node_modules/@esbuild/aix-ppc64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
- "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/android-arm": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
- "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/android-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
- "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/android-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
- "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/darwin-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
- "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/darwin-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
- "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
- "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/freebsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
- "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-arm": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
- "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
- "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-ia32": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
- "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-loong64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
- "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-mips64el": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
- "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-ppc64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
- "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-riscv64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
- "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-s390x": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
- "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/linux-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
- "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/netbsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
- "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/openbsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
- "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/sunos-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
- "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/win32-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
- "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/vite/node_modules/@esbuild/win32-ia32": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
- "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/vite/node_modules/@esbuild/win32-x64": {
"version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
- "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
"cpu": [
"x64"
],
@@ -10978,8 +12691,6 @@
},
"node_modules/vite/node_modules/esbuild": {
"version": "0.21.5",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
- "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -11017,8 +12728,6 @@
},
"node_modules/vitest": {
"version": "2.1.8",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.8.tgz",
- "integrity": "sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11083,10 +12792,10 @@
},
"node_modules/w3c-xmlserializer": {
"version": "5.0.0",
- "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
- "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"xml-name-validator": "^5.0.0"
},
@@ -11096,20 +12805,20 @@
},
"node_modules/webidl-conversions": {
"version": "7.0.0",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
- "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
"dev": true,
"license": "BSD-2-Clause",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=12"
}
},
"node_modules/whatwg-encoding": {
"version": "3.1.1",
- "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
- "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"iconv-lite": "0.6.3"
},
@@ -11119,10 +12828,10 @@
},
"node_modules/whatwg-encoding/node_modules/iconv-lite": {
"version": "0.6.3",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
- "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
@@ -11132,20 +12841,20 @@
},
"node_modules/whatwg-mimetype": {
"version": "4.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
- "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/whatwg-url": {
"version": "14.2.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
- "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
"tr46": "^5.1.0",
"webidl-conversions": "^7.0.0"
@@ -11156,9 +12865,7 @@
},
"node_modules/which": {
"version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
+ "devOptional": true,
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
@@ -11238,16 +12945,17 @@
}
},
"node_modules/which-typed-array": {
- "version": "1.1.18",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz",
- "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==",
+ "version": "1.1.19",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
+ "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
"dev": true,
"license": "MIT",
"dependencies": {
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "for-each": "^0.3.3",
+ "call-bound": "^1.0.4",
+ "for-each": "^0.3.5",
+ "get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-tostringtag": "^1.0.2"
},
@@ -11260,8 +12968,6 @@
},
"node_modules/why-is-node-running": {
"version": "2.3.0",
- "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
- "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11275,10 +12981,16 @@
"node": ">=8"
}
},
+ "node_modules/wide-align": {
+ "version": "1.1.5",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
"node_modules/winston": {
"version": "3.17.0",
- "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz",
- "integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==",
"license": "MIT",
"dependencies": {
"@colors/colors": "^1.6.0",
@@ -11299,8 +13011,6 @@
},
"node_modules/winston-transport": {
"version": "4.9.0",
- "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz",
- "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==",
"license": "MIT",
"dependencies": {
"logform": "^2.7.0",
@@ -11321,498 +13031,26 @@
"node": ">=0.10.0"
}
},
- "node_modules/wordwrap": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
- "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/workerd": {
- "version": "1.20241230.0",
- "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20241230.0.tgz",
- "integrity": "sha512-EgixXP0JGXGq6J9lz17TKIZtfNDUvJNG+cl9paPMfZuYWT920fFpBx+K04YmnbQRLnglsivF1GT9pxh1yrlWhg==",
- "dev": true,
- "hasInstallScript": true,
- "license": "Apache-2.0",
- "bin": {
- "workerd": "bin/workerd"
- },
- "engines": {
- "node": ">=16"
- },
- "optionalDependencies": {
- "@cloudflare/workerd-darwin-64": "1.20241230.0",
- "@cloudflare/workerd-darwin-arm64": "1.20241230.0",
- "@cloudflare/workerd-linux-64": "1.20241230.0",
- "@cloudflare/workerd-linux-arm64": "1.20241230.0",
- "@cloudflare/workerd-windows-64": "1.20241230.0"
- }
- },
- "node_modules/wrangler": {
- "version": "3.100.0",
- "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.100.0.tgz",
- "integrity": "sha512-+nsZK374Xnp2BEQQuB/18pnObgsOey0AHVlg75pAdwNaKAmB2aa0/E5rFb7i89DiiwFYoZMz3cARY1UKcm/WQQ==",
- "dev": true,
- "license": "MIT OR Apache-2.0",
- "dependencies": {
- "@cloudflare/kv-asset-handler": "0.3.4",
- "@esbuild-plugins/node-globals-polyfill": "^0.2.3",
- "@esbuild-plugins/node-modules-polyfill": "^0.2.2",
- "blake3-wasm": "^2.1.5",
- "chokidar": "^4.0.1",
- "date-fns": "^4.1.0",
- "esbuild": "0.17.19",
- "itty-time": "^1.0.6",
- "miniflare": "3.20241230.0",
- "nanoid": "^3.3.3",
- "path-to-regexp": "^6.3.0",
- "resolve": "^1.22.8",
- "selfsigned": "^2.0.1",
- "source-map": "^0.6.1",
- "unenv": "npm:unenv-nightly@2.0.0-20241218-183400-5d6aec3",
- "workerd": "1.20241230.0",
- "xxhash-wasm": "^1.0.1"
- },
- "bin": {
- "wrangler": "bin/wrangler.js",
- "wrangler2": "bin/wrangler.js"
- },
- "engines": {
- "node": ">=16.17.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- },
- "peerDependencies": {
- "@cloudflare/workers-types": "^4.20241230.0"
- },
- "peerDependenciesMeta": {
- "@cloudflare/workers-types": {
- "optional": true
- }
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/android-arm": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz",
- "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/android-arm64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz",
- "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/android-x64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz",
- "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/darwin-arm64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz",
- "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/darwin-x64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz",
- "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/freebsd-arm64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz",
- "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/freebsd-x64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz",
- "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/linux-arm": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz",
- "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/linux-arm64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz",
- "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/linux-ia32": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz",
- "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/linux-loong64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz",
- "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/linux-mips64el": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz",
- "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/linux-ppc64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz",
- "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/linux-riscv64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz",
- "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/linux-s390x": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz",
- "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/linux-x64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz",
- "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/netbsd-x64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz",
- "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/openbsd-x64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz",
- "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/sunos-x64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz",
- "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/win32-arm64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz",
- "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/win32-ia32": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz",
- "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/@esbuild/win32-x64": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz",
- "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/wrangler/node_modules/esbuild": {
- "version": "0.17.19",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz",
- "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/android-arm": "0.17.19",
- "@esbuild/android-arm64": "0.17.19",
- "@esbuild/android-x64": "0.17.19",
- "@esbuild/darwin-arm64": "0.17.19",
- "@esbuild/darwin-x64": "0.17.19",
- "@esbuild/freebsd-arm64": "0.17.19",
- "@esbuild/freebsd-x64": "0.17.19",
- "@esbuild/linux-arm": "0.17.19",
- "@esbuild/linux-arm64": "0.17.19",
- "@esbuild/linux-ia32": "0.17.19",
- "@esbuild/linux-loong64": "0.17.19",
- "@esbuild/linux-mips64el": "0.17.19",
- "@esbuild/linux-ppc64": "0.17.19",
- "@esbuild/linux-riscv64": "0.17.19",
- "@esbuild/linux-s390x": "0.17.19",
- "@esbuild/linux-x64": "0.17.19",
- "@esbuild/netbsd-x64": "0.17.19",
- "@esbuild/openbsd-x64": "0.17.19",
- "@esbuild/sunos-x64": "0.17.19",
- "@esbuild/win32-arm64": "0.17.19",
- "@esbuild/win32-ia32": "0.17.19",
- "@esbuild/win32-x64": "0.17.19"
- }
- },
- "node_modules/wrangler/node_modules/path-to-regexp": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
- "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
@@ -11830,19 +13068,76 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
+ "node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
"node_modules/wrappy": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true,
"license": "ISC"
},
"node_modules/ws": {
"version": "8.18.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
- "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=10.0.0"
},
@@ -11861,101 +13156,53 @@
},
"node_modules/xml-name-validator": {
"version": "5.0.0",
- "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
- "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
"dev": true,
"license": "Apache-2.0",
+ "optional": true,
+ "peer": true,
"engines": {
"node": ">=18"
}
},
"node_modules/xmlchars": {
"version": "2.2.0",
- "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
- "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "optional": true,
+ "peer": true
},
"node_modules/xtend": {
"version": "4.0.2",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
- "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.4"
}
},
- "node_modules/xxhash-wasm": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz",
- "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/yallist": {
"version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true,
"license": "ISC"
},
"node_modules/yaml": {
- "version": "1.10.2",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
- "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
- "license": "ISC",
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/yargs": {
- "version": "17.7.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
- "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
+ "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
"dev": true,
- "license": "MIT",
- "dependencies": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
},
"engines": {
- "node": ">=12"
+ "node": ">= 14.6"
}
},
- "node_modules/yargs-parser": {
- "version": "20.2.9",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
- "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
+ "node_modules/yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true,
- "license": "ISC",
+ "license": "MIT",
"engines": {
- "node": ">=10"
- }
- },
- "node_modules/yargs/node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=12"
+ "node": ">=6"
}
},
"node_modules/yocto-queue": {
@@ -11971,133 +13218,292 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/youch": {
- "version": "3.3.4",
- "resolved": "https://registry.npmjs.org/youch/-/youch-3.3.4.tgz",
- "integrity": "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cookie": "^0.7.1",
- "mustache": "^4.2.0",
- "stacktracey": "^2.1.8"
- }
- },
"node_modules/zod": {
- "version": "3.24.1",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz",
- "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==",
- "dev": true,
+ "version": "3.24.4",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
- "packages/addon": {
- "name": "@aiostreams/addon",
- "version": "1.21.1",
+ "node_modules/zwitch": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
+ "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "packages/core": {
+ "name": "@aiostreams/core",
+ "version": "0.0.0",
"dependencies": {
- "@aiostreams/formatters": "^1.0.0",
- "@aiostreams/types": "^1.0.0",
- "@aiostreams/utils": "^1.0.0",
- "@aiostreams/wrappers": "^1.0.0",
+ "bcrypt": "^6.0.0",
"dotenv": "^16.4.7",
- "express": "^4.21.2"
+ "envalid": "^8.0.0",
+ "expr-eval": "^2.0.2",
+ "moment-timezone": "^0.5.48",
+ "parse-torrent-title": "github:TheBeastLT/parse-torrent-title",
+ "pg": "^8.16.0",
+ "sqlite": "^5.1.1",
+ "sqlite3": "^5.1.7",
+ "super-regex": "^1.0.0",
+ "undici": "^7.2.3",
+ "winston": "^3.17.0",
+ "zod": "^3.24.4"
},
"devDependencies": {
- "@types/express": "^5.0.0"
- }
- },
- "packages/cloudflare-worker": {
- "name": "@aiostreams/cloudflare-worker",
- "version": "1.21.1",
- "dependencies": {
- "@aiostreams/addon": "^1.0.0",
- "@aiostreams/types": "^1.0.0"
- },
- "devDependencies": {
- "@cloudflare/workers-types": "^4.20241224.0",
- "typescript": "^5.5.2",
- "wrangler": "^3.99.0"
- }
- },
- "packages/cloudflare-workers": {
- "name": "@aiostreams/cloudflare-workers",
- "version": "1.1.0",
- "extraneous": true,
- "dependencies": {
- "@aiostreams/addon": "^1.0.0"
- },
- "devDependencies": {
- "@cloudflare/vitest-pool-workers": "^0.5.2",
- "@cloudflare/workers-types": "^4.20241224.0",
- "typescript": "^5.5.2",
- "vitest": "2.1.8",
- "wrangler": "^3.99.0"
- }
- },
- "packages/formatters": {
- "name": "@aiostreams/formatters",
- "version": "1.21.1",
- "dependencies": {
- "@aiostreams/types": "^1.0.0",
- "@aiostreams/utils": "^1.0.0"
+ "@types/bcrypt": "^5.0.2",
+ "@types/node": "^20.14.10",
+ "@types/pg": "^8.15.2"
}
},
"packages/frontend": {
"name": "@aiostreams/frontend",
- "version": "1.21.1",
+ "version": "0.0.0",
"dependencies": {
- "@aiostreams/addon": "^1.0.0",
- "@aiostreams/formatters": "^1.0.0",
- "@aiostreams/types": "^1.0.0",
- "@aiostreams/wrappers": "^1.0.0",
- "dotenv": "^16.4.7",
- "next": "15.1.2",
+ "@aiostreams/core": "^0.0.0",
+ "@dnd-kit/core": "^6.3.1",
+ "@dnd-kit/modifiers": "^9.0.0",
+ "@dnd-kit/sortable": "^10.0.0",
+ "@headlessui/react": "^2.2.4",
+ "@headlessui/tailwindcss": "^0.2.2",
+ "@radix-ui/react-accordion": "^1.2.11",
+ "@radix-ui/react-dialog": "^1.1.14",
+ "@radix-ui/react-dropdown-menu": "^2.1.15",
+ "@radix-ui/react-popover": "^1.1.14",
+ "@radix-ui/react-select": "^2.2.5",
+ "@radix-ui/react-separator": "^1.1.7",
+ "@radix-ui/react-slider": "^1.3.5",
+ "@radix-ui/react-switch": "^1.2.5",
+ "@radix-ui/react-tabs": "^1.1.12",
+ "@radix-ui/react-tooltip": "^1.2.7",
+ "@tailwindcss/forms": "^0.5.10",
+ "@tailwindcss/typography": "^0.5.16",
+ "@zag-js/number-input": "^1.13.1",
+ "@zag-js/react": "^1.13.1",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "cmdk": "^1.1.1",
+ "framer-motion": "^12.12.2",
+ "lucide-react": "^0.511.0",
+ "next": "15.3.2",
+ "next-themes": "^0.4.6",
"react": "^19.0.0",
"react-dom": "^19.0.0",
- "react-select": "^5.9.0",
- "react-toastify": "^11.0.2"
+ "react-icons": "^5.5.0",
+ "react-markdown": "^10.1.0",
+ "sonner": "^2.0.3",
+ "tailwind-merge": "^3.3.0",
+ "tailwind-scrollbar-hide": "~1.1.7",
+ "tailwindcss-animate": "~1.0.7"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
+ "@tailwindcss/postcss": "^4",
+ "@types/node": "^20",
+ "@types/react": "^19",
+ "@types/react-dom": "^19",
+ "autoprefixer": "^10.4.21",
+ "eslint": "^9",
+ "eslint-config-next": "15.3.2",
+ "postcss": "^8.5.3",
+ "postcss-import": "^16.1.0",
+ "postcss-nesting": "^13.0.1",
+ "tailwindcss": "^3.4.17",
+ "typescript": "^5"
+ }
+ },
+ "packages/frontend-temp": {
+ "version": "0.1.0",
+ "extraneous": true,
+ "dependencies": {
+ "next": "15.3.2",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0"
+ },
+ "devDependencies": {
+ "@eslint/eslintrc": "^3",
+ "@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
- "eslint-config-next": "15.1.2",
+ "eslint-config-next": "15.3.2",
+ "tailwindcss": "^4",
"typescript": "^5"
}
},
- "packages/parser": {
- "name": "@aiostreams/parser",
- "version": "1.21.1",
+ "packages/frontend/node_modules/arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "packages/frontend/node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@aiostreams/types": "^1.0.0",
- "parse-torrent-title": "github:TheBeastLT/parse-torrent-title"
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
}
},
- "packages/types": {
- "name": "@aiostreams/types",
- "version": "1.21.1"
- },
- "packages/utils": {
- "name": "@aiostreams/utils",
- "version": "1.21.1",
+ "packages/frontend/node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
"dependencies": {
- "envalid": "^8.0.0",
- "jsoncrush": "^1.1.8",
- "winston": "^3.17.0"
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
}
},
- "packages/wrappers": {
- "name": "@aiostreams/wrappers",
- "version": "1.21.1",
+ "packages/frontend/node_modules/jiti": {
+ "version": "1.21.7",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
+ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
+ "packages/frontend/node_modules/postcss-import": {
+ "version": "16.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz",
+ "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@aiostreams/formatters": "^1.0.0",
- "@aiostreams/parser": "^1.0.0",
- "@aiostreams/types": "^1.0.0",
- "@aiostreams/utils": "^1.0.0"
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "packages/frontend/node_modules/tailwindcss": {
+ "version": "3.4.17",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
+ "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.6.0",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.2",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.21.6",
+ "lilconfig": "^3.1.3",
+ "micromatch": "^4.0.8",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.1.1",
+ "postcss": "^8.4.47",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.2",
+ "postcss-nested": "^6.2.0",
+ "postcss-selector-parser": "^6.1.2",
+ "resolve": "^1.22.8",
+ "sucrase": "^3.35.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "packages/frontend/node_modules/tailwindcss/node_modules/postcss-import": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
+ "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "packages/frontend/node_modules/tailwindcss/node_modules/postcss-load-config": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
+ "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "lilconfig": "^3.0.0",
+ "yaml": "^2.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ },
+ "peerDependencies": {
+ "postcss": ">=8.0.9",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "postcss": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "packages/server": {
+ "name": "@aiostreams/server",
+ "version": "0.0.0",
+ "dependencies": {
+ "@aiostreams/core": "^0.0.0",
+ "express": "^4.21.2",
+ "express-rate-limit": "^7.5.0"
+ },
+ "devDependencies": {
+ "@types/express": "^5.0.1",
+ "@types/express-rate-limit": "^5.1.3",
+ "@types/node": "^20.14.10"
}
}
}
diff --git a/package.json b/package.json
index 9c61df8a..44d8019a 100644
--- a/package.json
+++ b/package.json
@@ -1,21 +1,20 @@
{
"name": "aiostreams",
"version": "1.22.0",
- "description": "Stremio addon to combine streams into one addon",
- "main": "dist/server.js",
+ "description": "AIOStreams consolidates multiple Stremio addons and debrid services into a single, easily configurable addon. It allows highly customisable filtering, sorting, and formatting of results and supports proxying all your streams through MediaFlow Proxy or StremThru for improved compatibility and IP restriction bypassing.",
+ "main": "dist/index.js",
"scripts": {
"test": "npm run test --workspaces",
"release": "commit-and-tag-version",
"format": "prettier --write .",
- "build": "npm -w packages/types run build && npm -w packages/utils run build && npm -w packages/parser run build && npm -w packages/formatters run build && npm -w packages/wrappers run build && npm -w packages/addon run build && npm -w packages/frontend run build",
+ "metadata": "node scripts/generateMetadata.js",
+ "build": "npm -w packages/core run build && npm -w packages/server run build && npm -w packages/frontend run build",
"build:watch": "tsc --build --watch",
- "start": "npm -w packages/addon start",
- "start:addon": "npm -w packages/addon start",
- "start:addon:dev": "npm -w packages/addon run start:dev",
- "start:frontend:dev": "npm -w packages/frontend run dev",
- "start:cloudflare-worker:dev": "npm -w packages/cloudflare-worker run dev",
- "deploy:beamup": "beamup",
- "deploy:cloudflare-worker": "npm -w packages/cloudflare-worker run deploy"
+ "start": "node packages/server/dist/server",
+ "start:addon": "npm run start",
+ "start:dev": "cross-env NODE_ENV=development tsx watch packages/server/src/server.ts",
+ "start:addon:dev": "npm run start:dev",
+ "start:frontend:dev": "npm -w packages/frontend run dev"
},
"author": "Viren070",
"license": "MIT",
@@ -23,20 +22,14 @@
"packages/*"
],
"devDependencies": {
- "@types/node": "^20.14.10",
- "beamup-cli": "^1.3.0",
- "commit-and-tag-version": "^12.5.0",
"cross-env": "^7.0.3",
"prettier": "^3.3.2",
"tsx": "^4.16.2",
"typescript": "^5.5.3",
- "vitest": "^2.1.5"
+ "vitest": "^2.1.5",
+ "ts-node": "^10.9.2"
},
"engines": {
"node": ">=20.0.0"
- },
- "dependencies": {
- "super-regex": "^1.0.0",
- "undici": "^7.2.3"
}
-}
+}
\ No newline at end of file
diff --git a/packages/addon/package.json b/packages/addon/package.json
deleted file mode 100644
index d1675917..00000000
--- a/packages/addon/package.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "name": "@aiostreams/addon",
- "version": "1.21.1",
- "main": "dist/index.js",
- "scripts": {
- "test": "vitest run --passWithNoTests",
- "test:watch": "vitest watch",
- "build": "tsc",
- "prepublish": "npm run build",
- "start": "node dist/server.js",
- "start:dev": "cross-env NODE_ENV=dev tsx watch src/server.ts"
- },
- "description": "Combine all your streams into one addon and display them with consistent formatting, sorting, and filtering.",
- "dependencies": {
- "@aiostreams/formatters": "^1.0.0",
- "@aiostreams/types": "^1.0.0",
- "@aiostreams/utils": "^1.0.0",
- "@aiostreams/wrappers": "^1.0.0",
- "dotenv": "^16.4.7",
- "express": "^4.21.2"
- },
- "devDependencies": {
- "@types/express": "^5.0.0"
- }
-}
diff --git a/packages/addon/src/addon.ts b/packages/addon/src/addon.ts
deleted file mode 100644
index caf6e363..00000000
--- a/packages/addon/src/addon.ts
+++ /dev/null
@@ -1,1416 +0,0 @@
-import {
- BaseWrapper,
- getCometStreams,
- getDebridioStreams,
- getDMMCastStreams,
- getEasynewsPlusPlusStreams,
- getEasynewsPlusStreams,
- getEasynewsStreams,
- getJackettioStreams,
- getMediafusionStreams,
- getOrionStreams,
- getPeerflixStreams,
- getStremioJackettStreams,
- getStremThruStoreStreams,
- getTorboxStreams,
- getTorrentioStreams,
-} from '@aiostreams/wrappers';
-import {
- Stream,
- ParsedStream,
- StreamRequest,
- Config,
- ErrorStream,
-} from '@aiostreams/types';
-import {
- gdriveFormat,
- torrentioFormat,
- torboxFormat,
- imposterFormat,
- customFormat,
-} from '@aiostreams/formatters';
-import {
- addonDetails,
- getMediaFlowConfig,
- getMediaFlowPublicIp,
- getTimeTakenSincePoint,
- Settings,
- createLogger,
- generateMediaFlowStreams,
- getStremThruConfig,
- getStremThruPublicIp,
- generateStremThruStreams,
- safeRegexTest,
- compileRegex,
- formRegexFromKeywords,
-} from '@aiostreams/utils';
-import { errorStream } from './responses';
-import { isMatch } from 'super-regex';
-
-const logger = createLogger('addon');
-
-export class AIOStreams {
- private config: Config;
-
- constructor(config: any) {
- this.config = config;
- }
-
- private async retryGetIp(
- getter: () => Promise,
- label: string,
- maxRetries: number = 3
- ): Promise {
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
- const result = await getter();
- if (result) {
- return result;
- }
- logger.warn(
- `Failed to get ${label}, retrying... (${attempt}/${maxRetries})`
- );
- }
- throw new Error(`Failed to get ${label} after ${maxRetries} attempts`);
- }
-
- private async getRequestingIp() {
- let userIp = this.config.requestingIp;
- const PRIVATE_IP_REGEX =
- /^(::1|::ffff:(10|127|192|172)\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})|10\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})|127\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})|192\.168\.(\d{1,3})\.(\d{1,3})|172\.(1[6-9]|2[0-9]|3[0-1])\.(\d{1,3})\.(\d{1,3}))$/;
-
- if (userIp && PRIVATE_IP_REGEX.test(userIp)) {
- userIp = undefined;
- }
- const mediaflowConfig = getMediaFlowConfig(this.config);
- const stremThruConfig = getStremThruConfig(this.config);
- if (mediaflowConfig.mediaFlowEnabled) {
- userIp = await this.retryGetIp(
- () => getMediaFlowPublicIp(mediaflowConfig),
- 'MediaFlow public IP'
- );
- } else if (stremThruConfig.stremThruEnabled) {
- userIp = await this.retryGetIp(
- () => getStremThruPublicIp(stremThruConfig),
- 'StremThru public IP'
- );
- }
- return userIp;
- }
-
- public async getStreams(streamRequest: StreamRequest): Promise {
- const streams: Stream[] = [];
- const startTime = new Date().getTime();
-
- try {
- this.config.requestingIp = await this.getRequestingIp();
- } catch (error) {
- logger.error(error);
- return [errorStream(`Failed to get Proxy IP`)];
- }
-
- const { parsedStreams, errorStreams } =
- await this.getParsedStreams(streamRequest);
-
- const skipReasons = {
- excludeLanguages: 0,
- excludeResolutions: 0,
- excludeQualities: 0,
- excludeEncodes: 0,
- excludeAudioTags: 0,
- excludeVisualTags: 0,
- excludeStreamTypes: 0,
- excludeUncached: 0,
- sizeFilters: 0,
- duplicateStreams: 0,
- streamLimiters: 0,
- excludeRegex: 0,
- requiredRegex: 0,
- };
-
- logger.info(
- `Got ${parsedStreams.length} parsed streams and ${errorStreams.length} error streams in ${getTimeTakenSincePoint(startTime)}`
- );
-
- const excludeRegexPattern = this.config.apiKey
- ? this.config.regexFilters?.excludePattern ||
- Settings.DEFAULT_REGEX_EXCLUDE_PATTERN
- : undefined;
- const excludeRegex = excludeRegexPattern
- ? compileRegex(excludeRegexPattern, 'i')
- : undefined;
-
- const excludeKeywordsRegex = this.config.excludeFilters
- ? formRegexFromKeywords(this.config.excludeFilters)
- : undefined;
-
- const requiredRegexPattern = this.config.apiKey
- ? this.config.regexFilters?.includePattern ||
- Settings.DEFAULT_REGEX_INCLUDE_PATTERN
- : undefined;
- const requiredRegex = requiredRegexPattern
- ? compileRegex(requiredRegexPattern, 'i')
- : undefined;
-
- const requiredKeywordsRegex = this.config.strictIncludeFilters
- ? formRegexFromKeywords(this.config.strictIncludeFilters)
- : undefined;
-
- const sortRegexPatterns = this.config.apiKey
- ? this.config.regexSortPatterns || Settings.DEFAULT_REGEX_SORT_PATTERNS
- : undefined;
-
- const sortRegexes: { name?: string; regex: RegExp }[] | undefined =
- sortRegexPatterns
- ? sortRegexPatterns
- .split(/\s+/)
- .filter(Boolean)
- .map((pattern) => {
- const delimiter = '<::>';
- const delimiterIndex = pattern.indexOf(delimiter);
- if (delimiterIndex !== -1) {
- const name = pattern
- .slice(0, delimiterIndex)
- .replace(/_/g, ' ');
- const regexPattern = pattern.slice(
- delimiterIndex + delimiter.length
- );
-
- const regex = compileRegex(regexPattern, 'i');
- return { name, regex };
- }
- return { regex: compileRegex(pattern, 'i') };
- })
- : undefined;
-
- excludeRegex ||
- excludeKeywordsRegex ||
- requiredRegex ||
- requiredKeywordsRegex ||
- sortRegexes
- ? logger.debug(
- `The following regex patterns are being used:\n` +
- `Exclude Regex: ${excludeRegex}\n` +
- `Exclude Keywords: ${excludeKeywordsRegex}\n` +
- `Required Regex: ${requiredRegex}\n` +
- `Required Keywords: ${requiredKeywordsRegex}\n` +
- `Sort Regexes: ${sortRegexes?.map((regex) => `${regex.name || 'Unnamed'}: ${regex.regex}`).join(' --> ')}\n`
- )
- : [];
-
- const filterStartTime = new Date().getTime();
-
- let filteredResults = parsedStreams.filter((parsedStream) => {
- const streamTypeFilter = this.config.streamTypes?.find(
- (streamType) => streamType[parsedStream.type] === false
- );
- if (this.config.streamTypes && streamTypeFilter) {
- skipReasons.excludeStreamTypes++;
- return false;
- }
-
- const resolutionFilter = this.config.resolutions?.find(
- (resolution) => resolution[parsedStream.resolution] === false
- );
- if (resolutionFilter) {
- skipReasons.excludeResolutions++;
- return false;
- }
-
- const qualityFilter = this.config.qualities?.find(
- (quality) => quality[parsedStream.quality] === false
- );
- if (this.config.qualities && qualityFilter) {
- skipReasons.excludeQualities++;
- return false;
- }
-
- // Check for HDR and DV tags in the parsed stream
- const hasHDR = parsedStream.visualTags.some((tag) =>
- tag.startsWith('HDR')
- );
- const hasDV = parsedStream.visualTags.includes('DV');
- const hasHDRAndDV = hasHDR && hasDV;
- const HDRAndDVEnabled = this.config.visualTags.some(
- (visualTag) => visualTag['HDR+DV'] === true
- );
-
- const isTagDisabled = (tag: string) =>
- this.config.visualTags.some((visualTag) => visualTag[tag] === false);
-
- if (hasHDRAndDV) {
- if (!HDRAndDVEnabled) {
- skipReasons.excludeVisualTags++;
- return false;
- }
- } else if (hasHDR) {
- const specificHdrTags = parsedStream.visualTags.filter((tag) =>
- tag.startsWith('HDR')
- );
- const disabledTags = specificHdrTags.filter(
- (tag) => isTagDisabled(tag) === true
- );
- if (disabledTags.length > 0) {
- skipReasons.excludeVisualTags++;
- return;
- }
- } else if (hasDV && isTagDisabled('DV')) {
- skipReasons.excludeVisualTags++;
- return false;
- }
-
- // Check other visual tags for explicit disabling
- for (const tag of parsedStream.visualTags) {
- if (tag.startsWith('HDR') || tag === 'DV') continue;
- if (isTagDisabled(tag)) {
- skipReasons.excludeVisualTags++;
- return false;
- }
- }
-
- // apply excludedLanguages filter
- const excludedLanguages = this.config.excludedLanguages;
- if (excludedLanguages && parsedStream.languages.length > 0) {
- if (
- parsedStream.languages.every((lang) =>
- excludedLanguages.includes(lang)
- )
- ) {
- skipReasons.excludeLanguages++;
- return false;
- }
- } else if (
- excludedLanguages &&
- excludedLanguages.includes('Unknown') &&
- parsedStream.languages.length === 0
- ) {
- skipReasons.excludeLanguages++;
- return false;
- }
-
- const audioTagFilter = parsedStream.audioTags.find((tag) =>
- this.config.audioTags.some((audioTag) => audioTag[tag] === false)
- );
- if (audioTagFilter) {
- skipReasons.excludeAudioTags++;
- return false;
- }
-
- if (
- parsedStream.encode &&
- this.config.encodes.some(
- (encode) => encode[parsedStream.encode] === false
- )
- ) {
- skipReasons.excludeEncodes++;
- return false;
- }
-
- if (
- this.config.onlyShowCachedStreams &&
- parsedStream.provider &&
- !parsedStream.provider.cached
- ) {
- skipReasons.excludeUncached++;
- return false;
- }
-
- if (
- this.config.minSize &&
- parsedStream.size &&
- parsedStream.size < this.config.minSize
- ) {
- skipReasons.sizeFilters++;
- return false;
- }
-
- if (
- this.config.maxSize &&
- parsedStream.size &&
- parsedStream.size > this.config.maxSize
- ) {
- skipReasons.sizeFilters++;
- return false;
- }
-
- if (
- streamRequest.type === 'movie' &&
- this.config.maxMovieSize &&
- parsedStream.size &&
- parsedStream.size > this.config.maxMovieSize
- ) {
- skipReasons.sizeFilters++;
- return false;
- }
-
- if (
- streamRequest.type === 'movie' &&
- this.config.minMovieSize &&
- parsedStream.size &&
- parsedStream.size < this.config.minMovieSize
- ) {
- skipReasons.sizeFilters++;
- return false;
- }
-
- if (
- streamRequest.type === 'series' &&
- this.config.maxEpisodeSize &&
- parsedStream.size &&
- parsedStream.size > this.config.maxEpisodeSize
- ) {
- skipReasons.sizeFilters++;
- return false;
- }
-
- if (
- streamRequest.type === 'series' &&
- this.config.minEpisodeSize &&
- parsedStream.size &&
- parsedStream.size < this.config.minEpisodeSize
- ) {
- skipReasons.sizeFilters++;
- return false;
- }
-
- // generate array of excludeTests. for each regex, only add to array if the filename or indexers are defined
- let excludeTests: (boolean | null)[] = [];
- let requiredTests: (boolean | null)[] = [];
-
- const addToTests = (field: string | undefined) => {
- if (field) {
- excludeTests.push(
- excludeRegex ? safeRegexTest(excludeRegex, field) : null,
- excludeKeywordsRegex
- ? safeRegexTest(excludeKeywordsRegex, field)
- : null
- );
- requiredTests.push(
- requiredRegex ? safeRegexTest(requiredRegex, field) : null,
- requiredKeywordsRegex
- ? safeRegexTest(requiredKeywordsRegex, field)
- : null
- );
- }
- };
-
- addToTests(parsedStream.filename);
- addToTests(parsedStream.folderName);
- addToTests(parsedStream.indexers);
-
- // filter out any null values as these are when the regex is not defined
- excludeTests = excludeTests.filter((test) => test !== null);
- requiredTests = requiredTests.filter((test) => test !== null);
-
- if (excludeTests.length > 0 && excludeTests.some((test) => test)) {
- skipReasons.excludeRegex++;
- return false;
- }
-
- if (requiredTests.length > 0 && !requiredTests.some((test) => test)) {
- skipReasons.requiredRegex++;
- return false;
- }
-
- return true;
- });
-
- logger.info(
- `Initial filter to ${filteredResults.length} streams in ${getTimeTakenSincePoint(filterStartTime)}`
- );
-
- if (this.config.cleanResults) {
- const cleanedStreams: ParsedStream[] = [];
- const initialStreams = filteredResults;
- const normaliseFilename = (filename?: string): string | undefined =>
- filename
- ? filename
- ?.replace(
- /\.(mkv|mp4|avi|mov|wmv|flv|webm|m4v|mpg|mpeg|3gp|3g2|m2ts|ts|vob|ogv|ogm|divx|xvid|rm|rmvb|asf|mxf|mka|mks|mk3d|webm|f4v|f4p|f4a|f4b)$/i,
- ''
- )
- .replace(/[^\p{L}\p{N}+]/gu, '')
- .replace(/\s+/g, '')
- .toLowerCase()
- : undefined;
-
- const groupStreamsByKey = (
- streams: ParsedStream[],
- keyExtractor: (stream: ParsedStream) => string | undefined
- ): Record => {
- return streams.reduce(
- (acc, stream) => {
- const key = keyExtractor(stream);
- if (!key) {
- if (!cleanedStreams.includes(stream)) {
- cleanedStreams.push(stream);
- }
- return acc;
- }
- acc[key] = acc[key] || [];
- acc[key].push(stream);
- return acc;
- },
- {} as Record
- );
- };
-
- const cleanResultsStartTime = new Date().getTime();
- // Deduplication by normalised filename
- const cleanResultsByFilenameStartTime = new Date().getTime();
- logger.info(`Received ${initialStreams.length} streams to clean`);
- const streamsGroupedByFilename = groupStreamsByKey(
- initialStreams,
- (stream) => normaliseFilename(stream.filename)
- );
-
- logger.info(
- `Found ${Object.keys(streamsGroupedByFilename).length} unique filenames with ${
- initialStreams.length -
- Object.values(streamsGroupedByFilename).reduce(
- (sum, group) => sum + group.length,
- 0
- )
- } streams not grouped`
- );
-
- // Process grouped streams by filename
- const cleanedStreamsByFilename = await this.processGroupedStreams(
- streamsGroupedByFilename
- );
-
- logger.info(
- `Deduplicated streams by filename to ${cleanedStreamsByFilename.length} streams in ${getTimeTakenSincePoint(cleanResultsByFilenameStartTime)}`
- );
-
- // Deduplication by hash
- const cleanResultsByHashStartTime = new Date().getTime();
-
- const streamsGroupedByHash = groupStreamsByKey(
- cleanedStreamsByFilename,
- (stream) => stream._infoHash
- );
- logger.info(
- `Found ${Object.keys(streamsGroupedByHash).length} unique hashes with ${cleanedStreamsByFilename.length - Object.values(streamsGroupedByHash).reduce((sum, group) => sum + group.length, 0)} streams not grouped`
- );
-
- // Process grouped streams by hash
- const cleanedStreamsByHash =
- await this.processGroupedStreams(streamsGroupedByHash);
-
- logger.info(
- `Deduplicated streams by hash to ${cleanedStreamsByHash.length} streams in ${getTimeTakenSincePoint(cleanResultsByHashStartTime)}`
- );
-
- cleanedStreams.push(...cleanedStreamsByHash);
- logger.info(
- `Deduplicated streams to ${cleanedStreams.length} streams in ${getTimeTakenSincePoint(cleanResultsStartTime)}`
- );
- skipReasons.duplicateStreams =
- filteredResults.length - cleanedStreams.length;
- filteredResults = cleanedStreams;
- }
- // pre compute highest indexes for regexSortPatterns
- const startPrecomputeTime = new Date().getTime();
- filteredResults.forEach((stream: ParsedStream) => {
- if (sortRegexes) {
- for (let i = 0; i < sortRegexes.length; i++) {
- if (!stream.filename && !stream.folderName) continue;
- const regex = sortRegexes[i];
- if (
- (stream.filename && isMatch(regex.regex, stream.filename)) ||
- (stream.folderName && isMatch(regex.regex, stream.folderName))
- ) {
- stream.regexMatched = {
- name: regex.name,
- pattern: regex.regex.source,
- index: i,
- };
- break;
- }
- }
- }
- });
- logger.info(
- `Precomputed sortRegex indexes for ${filteredResults.length} streams in ${getTimeTakenSincePoint(
- startPrecomputeTime
- )}`
- );
- // Apply sorting
- const sortStartTime = new Date().getTime();
- // initially sort by filename to ensure consistent results
- filteredResults.sort((a, b) =>
- a.filename && b.filename ? a.filename.localeCompare(b.filename) : 0
- );
-
- // then apply our this.config sorting
- filteredResults.sort((a, b) => {
- for (const sortByField of this.config.sortBy) {
- const field = Object.keys(sortByField).find(
- (key) => typeof sortByField[key] === 'boolean'
- );
- if (!field) continue;
- const value = sortByField[field];
-
- if (value) {
- const fieldComparison = this.compareByField(a, b, field);
- if (fieldComparison !== 0) return fieldComparison;
- }
- }
-
- return 0;
- });
-
- logger.info(`Sorted results in ${getTimeTakenSincePoint(sortStartTime)}`);
-
- // apply config.maxResultsPerResolution
- if (this.config.maxResultsPerResolution) {
- const startTime = new Date().getTime();
- const resolutionCounts = new Map();
-
- const limitedResults = filteredResults.filter((result) => {
- const resolution = result.resolution || 'Unknown';
- const currentCount = resolutionCounts.get(resolution) || 0;
-
- if (currentCount < this.config.maxResultsPerResolution!) {
- resolutionCounts.set(resolution, currentCount + 1);
- return true;
- }
-
- return false;
- });
- skipReasons.streamLimiters =
- filteredResults.length - limitedResults.length;
- filteredResults = limitedResults;
-
- logger.info(
- `Limited results to ${limitedResults.length} streams after applying maxResultsPerResolution in ${new Date().getTime() - startTime}ms`
- );
- }
-
- const totalSkipped = Object.values(skipReasons).reduce(
- (acc, val) => acc + val,
- 0
- );
- const reportLines = [
- '╔═══════════════════════╤════════════╗',
- '║ Skip Reason │ Count ║',
- '╟───────────────────────┼────────────╢',
- ...Object.entries(skipReasons)
- .filter(([reason, count]) => count > 0)
- .map(
- ([reason, count]) =>
- `║ ${reason.padEnd(21)} │ ${String(count).padStart(10)} ║`
- ),
- '╟───────────────────────┼────────────╢',
- `║ Total Skipped │ ${String(totalSkipped).padStart(10)} ║`,
- '╚═══════════════════════╧════════════╝',
- ];
-
- if (totalSkipped > 0) logger.info('\n' + reportLines.join('\n'));
-
- // Create stream objects
- const streamsStartTime = new Date().getTime();
- const streamObjects = await this.createStreamObjects(filteredResults);
- streams.push(...streamObjects.filter((s) => s !== null));
-
- // Add error streams to the end
- streams.push(
- ...errorStreams.map((e) => errorStream(e.error, e.addon.name))
- );
-
- logger.info(
- `Created ${streams.length} stream objects in ${getTimeTakenSincePoint(streamsStartTime)}`
- );
- logger.info(
- `Total time taken to get streams: ${getTimeTakenSincePoint(startTime)}`
- );
- return streams;
- }
-
- private shouldProxyStream(
- stream: ParsedStream,
- mediaFlowConfig: ReturnType,
- stremThruConfig: ReturnType
- ): boolean {
- if (!stream.url) return false;
-
- const streamProvider = stream.provider ? stream.provider.id : 'none';
-
- // // now check if mediaFlowConfig.proxiedAddons or mediaFlowConfig.proxiedServices is not null
- // logger.info(this.config.mediaFlowConfig?.proxiedAddons);
- // logger.info(stream.addon.id);
- if (
- mediaFlowConfig.mediaFlowEnabled &&
- (!mediaFlowConfig.proxiedAddons?.length ||
- mediaFlowConfig.proxiedAddons.includes(stream.addon.id)) &&
- (!mediaFlowConfig.proxiedServices?.length ||
- mediaFlowConfig.proxiedServices.includes(streamProvider))
- ) {
- return true;
- }
-
- if (
- stremThruConfig.stremThruEnabled &&
- (!stremThruConfig.proxiedAddons?.length ||
- stremThruConfig.proxiedAddons.includes(stream.addon.id)) &&
- (!stremThruConfig.proxiedServices?.length ||
- stremThruConfig.proxiedServices.includes(streamProvider))
- ) {
- return true;
- }
-
- return false;
- }
-
- private getFormattedText(parsedStream: ParsedStream): {
- name: string;
- description: string;
- } {
- switch (this.config.formatter) {
- case 'gdrive': {
- return gdriveFormat(parsedStream, false);
- }
- case 'minimalistic-gdrive': {
- return gdriveFormat(parsedStream, true);
- }
- case 'imposter': {
- return imposterFormat(parsedStream);
- }
- case 'torrentio': {
- return torrentioFormat(parsedStream);
- }
- case 'torbox': {
- return torboxFormat(parsedStream);
- }
- default: {
- if (
- this.config.formatter.startsWith('custom:') &&
- this.config.formatter.length > 7
- ) {
- const jsonString = this.config.formatter.slice(7);
- const formatter = JSON.parse(jsonString);
- if (formatter.name && formatter.description) {
- try {
- return customFormat(parsedStream, formatter);
- } catch (error: any) {
- logger.error(
- `Error in custom formatter: ${error.message || error}, falling back to default formatter`
- );
- return gdriveFormat(parsedStream, false);
- }
- }
- }
-
- return gdriveFormat(parsedStream, false);
- }
- }
- }
-
- private async createStreamObjects(
- parsedStreams: ParsedStream[]
- ): Promise {
- const mediaFlowConfig = getMediaFlowConfig(this.config);
- const stremThruConfig = getStremThruConfig(this.config);
-
- // Identify streams that require proxying
- const streamsToProxy = parsedStreams
- .map((stream, index) => ({ stream, index }))
- .filter(
- ({ stream }) =>
- stream.url &&
- this.shouldProxyStream(stream, mediaFlowConfig, stremThruConfig)
- );
-
- const proxiedUrls = streamsToProxy.length
- ? mediaFlowConfig.mediaFlowEnabled
- ? await generateMediaFlowStreams(
- mediaFlowConfig,
- streamsToProxy.map(({ stream }) => ({
- url: stream.url!,
- filename: stream.filename,
- headers: stream.stream?.behaviorHints?.proxyHeaders,
- }))
- )
- : stremThruConfig.stremThruEnabled
- ? await generateStremThruStreams(
- stremThruConfig,
- streamsToProxy.map(({ stream }) => ({
- url: stream.url!,
- filename: stream.filename,
- headers: stream.stream?.behaviorHints?.proxyHeaders,
- }))
- )
- : null
- : null;
-
- const removeIndexes = new Set();
-
- // Apply proxied URLs and mark as proxied
- streamsToProxy.forEach(({ stream, index }, i) => {
- const proxiedUrl = proxiedUrls?.[i];
- if (proxiedUrl) {
- stream.url = proxiedUrl;
- stream.proxied = true;
- } else {
- removeIndexes.add(index);
- }
- });
-
- // Remove streams that failed to proxy
- if (removeIndexes.size > 0) {
- logger.error(
- `Failed to proxy ${removeIndexes.size} streams, removing them from the final list`
- );
- parsedStreams = parsedStreams.filter(
- (_, index) => !removeIndexes.has(index)
- );
- }
-
- // Build final Stream objects
- const proxyBingeGroupPrefix = mediaFlowConfig.mediaFlowEnabled
- ? 'mfp.'
- : stremThruConfig.stremThruEnabled
- ? 'st.'
- : '';
- const streamObjects: Stream[] = await Promise.all(
- parsedStreams.map((parsedStream) => {
- const { name, description } = this.getFormattedText(parsedStream);
-
- const combinedTags = [
- parsedStream.resolution,
- parsedStream.quality,
- parsedStream.encode,
- ...parsedStream.visualTags,
- ...parsedStream.audioTags,
- ...parsedStream.languages,
- ];
-
- return {
- url: parsedStream.url,
- externalUrl: parsedStream.externalUrl,
- infoHash: parsedStream.torrent?.infoHash,
- fileIdx: parsedStream.torrent?.fileIdx,
- name,
- description,
- subtitles: parsedStream.stream?.subtitles,
- sources: parsedStream.torrent?.sources,
- behaviorHints: {
- videoSize: parsedStream.size
- ? Math.floor(parsedStream.size)
- : undefined,
- filename: parsedStream.filename,
- bingeGroup: `${parsedStream.proxied ? proxyBingeGroupPrefix : ''}${Settings.ADDON_ID}|${parsedStream.addon.name}|${combinedTags.join('|')}`,
- proxyHeaders: parsedStream.stream?.behaviorHints?.proxyHeaders,
- notWebReady: parsedStream.stream?.behaviorHints?.notWebReady,
- },
- };
- })
- );
-
- return streamObjects;
- }
-
- private compareLanguages(a: ParsedStream, b: ParsedStream) {
- if (this.config.prioritiseLanguage) {
- const aHasPrioritisedLanguage = a.languages.includes(
- this.config.prioritiseLanguage
- );
- const bHasPrioritisedLanguage = b.languages.includes(
- this.config.prioritiseLanguage
- );
-
- if (aHasPrioritisedLanguage && !bHasPrioritisedLanguage) return -1;
- if (!aHasPrioritisedLanguage && bHasPrioritisedLanguage) return 1;
- }
- return 0;
- }
-
- private compareByField(a: ParsedStream, b: ParsedStream, field: string) {
- if (field === 'resolution') {
- return (
- this.config.resolutions.findIndex(
- (resolution) => resolution[a.resolution]
- ) -
- this.config.resolutions.findIndex(
- (resolution) => resolution[b.resolution]
- )
- );
- } else if (field === 'regexSort') {
- const regexSortPatterns =
- this.config.regexSortPatterns || Settings.DEFAULT_REGEX_SORT_PATTERNS;
- if (!regexSortPatterns) return 0;
- try {
- // Get direction once
- const direction = this.config.sortBy.find(
- (sort) => Object.keys(sort)[0] === 'regexSort'
- )?.direction;
-
- // Early exit if no filename to test
- if (!a.filename && !b.filename) return 0;
- if (!a.filename) return direction === 'asc' ? -1 : 1;
- if (!b.filename) return direction === 'asc' ? 1 : -1;
-
- const aHighestIndex = a.regexMatched?.index;
- const bHighestIndex = b.regexMatched?.index;
-
- // If both have a regex match, sort by the highest index
- if (aHighestIndex !== undefined && bHighestIndex !== undefined) {
- return direction === 'asc'
- ? bHighestIndex - aHighestIndex
- : aHighestIndex - bHighestIndex;
- }
- // If one has a regex match and the other doesn't, sort by the one that does
- if (aHighestIndex !== undefined) return direction === 'asc' ? 1 : -1;
- if (bHighestIndex !== undefined) return direction === 'asc' ? -1 : 1;
-
- // If both have no regex match, they are equal
- return 0;
- } catch (e) {
- return 0;
- }
- } else if (field === 'cached') {
- let aCanbeCached = a.provider;
- let bCanbeCached = b.provider;
- let aCached = a.provider?.cached;
- let bCached = b.provider?.cached;
-
- // prioritise non debrid/usenet p2p over uncached
- if (aCanbeCached && !bCanbeCached && !aCached) return 1;
- if (!aCanbeCached && bCanbeCached && !bCached) return -1;
- if (aCanbeCached && bCanbeCached) {
- if (aCached === bCached) return 0;
- // prioritise a false value over undefined
- if (aCached === false && bCached === undefined) return -1;
- if (aCached === undefined && bCached === false) return 1;
- return this.config.sortBy.find(
- (sort) => Object.keys(sort)[0] === 'cached'
- )?.direction === 'asc'
- ? aCached
- ? 1
- : -1 // uncached > cached
- : aCached
- ? -1
- : 1; // cached > uncached
- }
- } else if (field === 'personal') {
- // depending on direction, sort by personal or not personal
- const direction = this.config.sortBy.find(
- (sort) => Object.keys(sort)[0] === 'personal'
- )?.direction;
- if (direction === 'asc') {
- // prefer not personal over personal
- return a.personal === b.personal ? 0 : a.personal ? 1 : -1;
- }
- if (direction === 'desc') {
- // prefer personal over not personal
- return a.personal === b.personal ? 0 : a.personal ? -1 : 1;
- }
- } else if (field === 'service') {
- // sort files with providers by name
- let aProvider = a.provider?.id;
- let bProvider = b.provider?.id;
-
- if (aProvider && bProvider) {
- const aIndex = this.config.services.findIndex(
- (service) => service.id === aProvider
- );
- const bIndex = this.config.services.findIndex(
- (service) => service.id === bProvider
- );
- return aIndex - bIndex;
- }
- } else if (field === 'size') {
- return this.config.sortBy.find((sort) => Object.keys(sort)[0] === 'size')
- ?.direction === 'asc'
- ? (a.size || 0) - (b.size || 0)
- : (b.size || 0) - (a.size || 0);
- } else if (field === 'seeders') {
- if (
- a.torrent?.seeders !== undefined &&
- b.torrent?.seeders !== undefined
- ) {
- return this.config.sortBy.find(
- (sort) => Object.keys(sort)[0] === 'seeders'
- )?.direction === 'asc'
- ? a.torrent.seeders - b.torrent.seeders
- : b.torrent.seeders - a.torrent.seeders;
- } else if (
- a.torrent?.seeders !== undefined &&
- b.torrent?.seeders === undefined
- ) {
- return -1;
- } else if (
- a.torrent?.seeders === undefined &&
- b.torrent?.seeders !== undefined
- ) {
- return 1;
- }
- } else if (field === 'streamType') {
- return (
- (this.config.streamTypes?.findIndex(
- (streamType) => streamType[a.type]
- ) ?? -1) -
- (this.config.streamTypes?.findIndex(
- (streamType) => streamType[b.type]
- ) ?? -1)
- );
- } else if (field === 'quality') {
- return (
- this.config.qualities.findIndex((quality) => quality[a.quality]) -
- this.config.qualities.findIndex((quality) => quality[b.quality])
- );
- } else if (field === 'visualTag') {
- // Find the highest priority visual tag in each file
- const getIndexOfTag = (tag: string) =>
- this.config.visualTags.findIndex((t) => t[tag]);
-
- const getHighestPriorityTagIndex = (tags: string[]) => {
- // Check if the file contains both any HDR tag and DV
- const hasHDR = tags.some((tag) => tag.startsWith('HDR'));
- const hasDV = tags.includes('DV');
-
- if (hasHDR && hasDV) {
- // Sort according to the position of the HDR+DV tag
- const hdrDvIndex = this.config.visualTags.findIndex(
- (t) => t['HDR+DV']
- );
- if (hdrDvIndex !== -1) {
- return hdrDvIndex;
- }
- }
-
- // If the file contains multiple HDR tags, look at the HDR tag that has the highest priority
- const hdrTagIndices = tags
- .filter((tag) => tag.startsWith('HDR'))
- .map((tag) => getIndexOfTag(tag));
- if (hdrTagIndices.length > 0) {
- return Math.min(...hdrTagIndices);
- }
-
- // Always consider the highest priority visual tag when a file has multiple visual tags
- return tags.reduce(
- (minIndex, tag) => Math.min(minIndex, getIndexOfTag(tag)),
- this.config.visualTags.length
- );
- };
-
- const aVisualTagIndex = getHighestPriorityTagIndex(a.visualTags);
- const bVisualTagIndex = getHighestPriorityTagIndex(b.visualTags);
-
- // Sort by the visual tag index
- return aVisualTagIndex - bVisualTagIndex;
- } else if (field === 'audioTag') {
- // Find the highest priority audio tag in each file
- const getIndexOfTag = (tag: string) =>
- this.config.audioTags.findIndex((t) => t[tag]);
- const aAudioTagIndex = a.audioTags.reduce(
- (minIndex, tag) => Math.min(minIndex, getIndexOfTag(tag)),
- this.config.audioTags.length
- );
-
- const bAudioTagIndex = b.audioTags.reduce(
- (minIndex, tag) => Math.min(minIndex, getIndexOfTag(tag)),
- this.config.audioTags.length
- );
- // Sort by the audio tag index
- return aAudioTagIndex - bAudioTagIndex;
- } else if (field === 'encode') {
- return (
- this.config.encodes.findIndex((encode) => encode[a.encode]) -
- this.config.encodes.findIndex((encode) => encode[b.encode])
- );
- } else if (field === 'addon') {
- const aAddon = a.addon.id;
- const bAddon = b.addon.id;
-
- const addonIds = this.config.addons.map((addon) => {
- return `${addon.id}-${JSON.stringify(addon.options)}`;
- });
- return addonIds.indexOf(aAddon) - addonIds.indexOf(bAddon);
- } else if (field === 'language') {
- if (this.config.prioritiseLanguage) {
- return this.compareLanguages(a, b);
- }
- if (!this.config.prioritisedLanguages) {
- return 0;
- }
- // else, we look at the array of prioritisedLanguages.
- // any file with a language in the prioritisedLanguages array should be prioritised
- // if both files contain a prioritisedLanguage, we compare the index of the highest priority language
-
- const aHasPrioritisedLanguage =
- a.languages.some((lang) =>
- this.config.prioritisedLanguages?.includes(lang)
- ) ||
- (a.languages.length === 0 &&
- this.config.prioritisedLanguages?.includes('Unknown'));
- const bHasPrioritisedLanguage =
- b.languages.some((lang) =>
- this.config.prioritisedLanguages?.includes(lang)
- ) ||
- (b.languages.length === 0 &&
- this.config.prioritisedLanguages?.includes('Unknown'));
-
- if (aHasPrioritisedLanguage && !bHasPrioritisedLanguage) return -1;
- if (!aHasPrioritisedLanguage && bHasPrioritisedLanguage) return 1;
-
- if (aHasPrioritisedLanguage && bHasPrioritisedLanguage) {
- const getHighestPriorityLanguageIndex = (languages: string[]) => {
- if (languages.length === 0) {
- const unknownIndex =
- this.config.prioritisedLanguages!.indexOf('Unknown');
- return unknownIndex !== -1
- ? unknownIndex
- : this.config.prioritisedLanguages!.length;
- }
- return languages.reduce((minIndex, lang) => {
- const index =
- this.config.prioritisedLanguages?.indexOf(lang) ??
- this.config.prioritisedLanguages!.length;
- return index !== -1 ? Math.min(minIndex, index) : minIndex;
- }, this.config.prioritisedLanguages!.length);
- };
-
- const aHighestPriorityLanguageIndex = getHighestPriorityLanguageIndex(
- a.languages
- );
- const bHighestPriorityLanguageIndex = getHighestPriorityLanguageIndex(
- b.languages
- );
-
- return aHighestPriorityLanguageIndex - bHighestPriorityLanguageIndex;
- }
- }
- return 0;
- }
-
- private async getParsedStreams(
- streamRequest: StreamRequest
- ): Promise<{ parsedStreams: ParsedStream[]; errorStreams: ErrorStream[] }> {
- const parsedStreams: ParsedStream[] = [];
- const errorStreams: ErrorStream[] = [];
- const formatError = (error: string) =>
- typeof error === 'string'
- ? error
- .replace(/- |: /g, '\n')
- .split('\n')
- .map((line: string) => line.trim())
- .join('\n')
- .trim()
- : error;
-
- const addonPromises = this.config.addons.map(async (addon) => {
- const addonName =
- addon.options.name ||
- addon.options.overrideName ||
- addonDetails.find((addonDetail) => addonDetail.id === addon.id)?.name ||
- addon.id;
- const addonId = `${addon.id}-${JSON.stringify(addon.options)}`;
- try {
- const startTime = new Date().getTime();
- const { addonStreams, addonErrors } = await this.getStreamsFromAddon(
- addon,
- addonId,
- streamRequest
- );
- parsedStreams.push(...addonStreams);
- errorStreams.push(
- ...[...new Set(addonErrors)].map((error) => ({
- error: formatError(error),
- addon: { id: addonId, name: addonName },
- }))
- );
- logger.info(
- `Got ${addonStreams.length} streams ${addonErrors.length > 0 ? `and ${addonErrors.length} errors ` : ''}from addon ${addonName} in ${getTimeTakenSincePoint(startTime)}`
- );
- } catch (error: any) {
- logger.error(`Failed to get streams from ${addonName}: ${error}`);
- errorStreams.push({
- error: formatError(error.message ?? error ?? 'Unknown error'),
- addon: {
- id: addonId,
- name: addonName,
- },
- });
- }
- });
-
- await Promise.all(addonPromises);
- return { parsedStreams, errorStreams };
- }
-
- private async getStreamsFromAddon(
- addon: Config['addons'][0],
- addonId: string,
- streamRequest: StreamRequest
- ): Promise<{ addonStreams: ParsedStream[]; addonErrors: string[] }> {
- switch (addon.id) {
- case 'torbox': {
- return await getTorboxStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'torrentio': {
- return await getTorrentioStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'comet': {
- return await getCometStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'mediafusion': {
- return await getMediafusionStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'stremio-jackett': {
- return await getStremioJackettStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'jackettio': {
- return await getJackettioStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'orion-stremio-addon': {
- return await getOrionStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'easynews': {
- return await getEasynewsStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'easynews-plus': {
- return await getEasynewsPlusStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'easynews-plus-plus': {
- return await getEasynewsPlusPlusStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'debridio': {
- return await getDebridioStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'peerflix': {
- return await getPeerflixStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'stremthru-store': {
- return await getStremThruStoreStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'dmm-cast': {
- return await getDMMCastStreams(
- this.config,
- addon.options,
- streamRequest,
- addonId
- );
- }
- case 'gdrive': {
- if (!addon.options.addonUrl) {
- throw new Error('The addon URL was undefined for GDrive');
- }
- const wrapper = new BaseWrapper(
- addon.options.overrideName || 'GDrive',
- addon.options.addonUrl,
- addonId,
- this.config,
- addon.options.indexerTimeout
- ? parseInt(addon.options.indexerTimeout)
- : Settings.DEFAULT_GDRIVE_TIMEOUT
- );
- return await wrapper.getParsedStreams(streamRequest);
- }
- default: {
- if (!addon.options.url) {
- throw new Error(
- `The addon URL was undefined for ${addon.options.name}`
- );
- }
- const wrapper = new BaseWrapper(
- addon.options.name || 'Custom',
- addon.options.url.trim(),
- addonId,
- this.config,
- addon.options.indexerTimeout
- ? parseInt(addon.options.indexerTimeout)
- : undefined
- );
- return wrapper.getParsedStreams(streamRequest);
- }
- }
- }
- private async processGroupedStreams(
- groupedStreams: Record
- ) {
- const uniqueStreams: ParsedStream[] = [];
- Object.values(groupedStreams).forEach((groupedStreams) => {
- if (groupedStreams.length === 1) {
- uniqueStreams.push(groupedStreams[0]);
- return;
- }
-
- /*logger.info(
- `==================\nDetermining unique streams for ${groupedStreams[0].filename} from ${groupedStreams.length} total duplicates`
- );
- logger.info(
- groupedStreams.map(
- (stream) =>
- `Addon ID: ${stream.addon.id}, Provider ID: ${stream.provider?.id}, Provider Cached: ${stream.provider?.cached}, type: ${stream.torrent ? 'torrent' : 'usenet'}`
- )
- );
- logger.info('==================');*/
- // Separate streams into categories
- const cachedStreams = groupedStreams.filter(
- (stream) => stream.provider?.cached || (!stream.provider && stream.url)
- );
- const uncachedStreams = groupedStreams.filter(
- (stream) => stream.provider && !stream.provider.cached
- );
- const noProviderStreams = groupedStreams.filter(
- (stream) => !stream.provider && stream.torrent?.infoHash
- );
-
- // Select uncached streams by addon priority (one per provider)
- const selectedUncachedStreams = Object.values(
- uncachedStreams.reduce(
- (acc, stream) => {
- acc[stream.provider!.id] = acc[stream.provider!.id] || [];
- acc[stream.provider!.id].push(stream);
- return acc;
- },
- {} as Record
- )
- ).map((providerGroup) => {
- return providerGroup.sort((a, b) => {
- const aIndex = this.config.addons.findIndex(
- (addon) =>
- `${addon.id}-${JSON.stringify(addon.options)}` === a.addon.id
- );
- const bIndex = this.config.addons.findIndex(
- (addon) =>
- `${addon.id}-${JSON.stringify(addon.options)}` === b.addon.id
- );
- return aIndex - bIndex;
- })[0];
- });
- //selectedUncachedStreams.forEach(stream => logger.info(`Selected uncached stream for provider ${stream.provider!.id}: Addon ID: ${stream.addon.id}`));
-
- // Select cached streams by provider and addon priority
- const selectedCachedStream = cachedStreams.sort((a, b) => {
- const aProviderIndex = this.config.services.findIndex(
- (service) => service.id === a.provider?.id
- );
- const bProviderIndex = this.config.services.findIndex(
- (service) => service.id === b.provider?.id
- );
-
- if (aProviderIndex !== bProviderIndex) {
- return aProviderIndex - bProviderIndex;
- }
-
- const aAddonIndex = this.config.addons.findIndex(
- (addon) =>
- `${addon.id}-${JSON.stringify(addon.options)}` === a.addon.id
- );
- const bAddonIndex = this.config.addons.findIndex(
- (addon) =>
- `${addon.id}-${JSON.stringify(addon.options)}` === b.addon.id
- );
-
- if (aAddonIndex !== bAddonIndex) {
- return aAddonIndex - bAddonIndex;
- }
-
- // now look at the type of stream. prefer usenet over torrents
- if (a.torrent?.seeders && !b.torrent?.seeders) return 1;
- if (!a.torrent?.seeders && b.torrent?.seeders) return -1;
- return 0;
- })[0];
- // Select one non-provider stream (highest addon priority)
- const selectedNoProviderStream = noProviderStreams.sort((a, b) => {
- const aIndex = this.config.addons.findIndex(
- (addon) =>
- `${addon.id}-${JSON.stringify(addon.options)}` === a.addon.id
- );
- const bIndex = this.config.addons.findIndex(
- (addon) =>
- `${addon.id}-${JSON.stringify(addon.options)}` === b.addon.id
- );
-
- if (aIndex !== bIndex) {
- return aIndex - bIndex;
- }
-
- // now look at the type of stream. prefer usenet over torrents
- if (a.torrent?.seeders && !b.torrent?.seeders) return 1;
- if (!a.torrent?.seeders && b.torrent?.seeders) return -1;
- return 0;
- })[0];
-
- // Combine selected streams for this group
- if (selectedNoProviderStream) {
- //logger.info(`Selected no provider stream: Addon ID: ${selectedNoProviderStream.addon.id}`);
- uniqueStreams.push(selectedNoProviderStream);
- }
- if (selectedCachedStream) {
- //logger.info(`Selected cached stream for provider ${selectedCachedStream.provider!.id} from Addon ID: ${selectedCachedStream.addon.id}`);
- uniqueStreams.push(selectedCachedStream);
- }
- uniqueStreams.push(...selectedUncachedStreams);
- });
-
- return uniqueStreams;
- }
-}
diff --git a/packages/addon/src/config.ts b/packages/addon/src/config.ts
deleted file mode 100644
index 619a1f21..00000000
--- a/packages/addon/src/config.ts
+++ /dev/null
@@ -1,537 +0,0 @@
-import { AddonDetail, Config } from '@aiostreams/types';
-import {
- addonDetails,
- isValueEncrypted,
- parseAndDecryptString,
- serviceDetails,
- Settings,
- unminifyConfig,
-} from '@aiostreams/utils';
-
-export const allowedFormatters = [
- 'gdrive',
- 'minimalistic-gdrive',
- 'torrentio',
- 'torbox',
- 'imposter',
- 'custom',
-];
-
-export const allowedLanguages = [
- 'Multi',
- 'English',
- 'Japanese',
- 'Chinese',
- 'Russian',
- 'Arabic',
- 'Portuguese',
- 'Spanish',
- 'French',
- 'German',
- 'Italian',
- 'Korean',
- 'Hindi',
- 'Bengali',
- 'Punjabi',
- 'Marathi',
- 'Gujarati',
- 'Tamil',
- 'Telugu',
- 'Kannada',
- 'Malayalam',
- 'Thai',
- 'Vietnamese',
- 'Indonesian',
- 'Turkish',
- 'Hebrew',
- 'Persian',
- 'Ukrainian',
- 'Greek',
- 'Lithuanian',
- 'Latvian',
- 'Estonian',
- 'Polish',
- 'Czech',
- 'Slovak',
- 'Hungarian',
- 'Romanian',
- 'Bulgarian',
- 'Serbian',
- 'Croatian',
- 'Slovenian',
- 'Dutch',
- 'Danish',
- 'Finnish',
- 'Swedish',
- 'Norwegian',
- 'Malay',
- 'Latino',
- 'Unknown',
- 'Dual Audio',
- 'Dubbed',
-];
-
-export function validateConfig(
- config: Config,
- environment: 'client' | 'server' = 'server'
-): {
- valid: boolean;
- errorCode: string | null;
- errorMessage: string | null;
-} {
- config = unminifyConfig(config);
- const createResponse = (
- valid: boolean,
- errorCode: string | null,
- errorMessage: string | null
- ) => {
- return { valid, errorCode, errorMessage };
- };
-
- if (config.addons.length < 1) {
- return createResponse(
- false,
- 'noAddons',
- 'At least one addon must be selected'
- );
- }
-
- if (config.addons.length > Settings.MAX_ADDONS) {
- return createResponse(
- false,
- 'tooManyAddons',
- `You can only select a maximum of ${Settings.MAX_ADDONS} addons`
- );
- }
- // check for apiKey if Settings.API_KEY is set
- if (environment === 'server' && Settings.API_KEY) {
- const { apiKey } = config;
- if (!apiKey) {
- return createResponse(
- false,
- 'missingApiKey',
- 'The AIOStreams API key is required'
- );
- }
- let decryptedApiKey = apiKey;
- if (isValueEncrypted(apiKey)) {
- const decryptionResult = parseAndDecryptString(apiKey);
- if (decryptionResult === null) {
- return createResponse(
- false,
- 'decryptionFailed',
- 'Failed to decrypt the AIOStreams API key'
- );
- } else if (decryptionResult === '') {
- return createResponse(
- false,
- 'emptyDecryption',
- 'Decrypted API key is empty'
- );
- }
- decryptedApiKey = decryptionResult;
- }
- if (decryptedApiKey !== Settings.API_KEY) {
- return createResponse(
- false,
- 'invalidApiKey',
- 'Invalid AIOStreams API key. Please use the one defined in your environment variables'
- );
- }
- }
- const duplicateAddons = config.addons.filter(
- (addon, index) =>
- config.addons.findIndex(
- (a) =>
- a.id === addon.id &&
- JSON.stringify(a.options) === JSON.stringify(addon.options)
- ) !== index
- );
-
- if (duplicateAddons.length > 0) {
- return createResponse(
- false,
- 'duplicateAddons',
- 'Duplicate addons found. Please remove any duplicates'
- );
- }
-
- for (const addon of config.addons) {
- if (Settings.DISABLE_TORRENTIO && addon.id === 'torrentio') {
- return createResponse(
- false,
- 'torrentioDisabled',
- Settings.DISABLE_TORRENTIO_MESSAGE
- );
- }
-
- const details = addonDetails.find(
- (detail: AddonDetail) => detail.id === addon.id
- );
- if (!details) {
- return createResponse(
- false,
- 'invalidAddon',
- `Invalid addon: ${addon.id}`
- );
- }
- if (details.requiresService) {
- const supportedServices = details.supportedServices;
- const isAtLeastOneServiceEnabled = config.services.some(
- (service) => supportedServices.includes(service.id) && service.enabled
- );
- const isOverrideUrlSet = addon.options?.overrideUrl;
- if (!isAtLeastOneServiceEnabled && !isOverrideUrlSet) {
- return createResponse(
- false,
- 'missingService',
- `${addon.options?.name || details.name} requires at least one of the following services to be enabled: ${supportedServices
- .map(
- (service) =>
- serviceDetails.find((detail) => detail.id === service)?.name ||
- service
- )
- .join(', ')}`
- );
- }
- }
- if (details.options) {
- for (const option of details.options) {
- if (option.required && !addon.options[option.id]) {
- return createResponse(
- false,
- 'missingRequiredOption',
- `Option ${option.label} is required for addon ${addon.id}`
- );
- }
-
- if (
- option.id.toLowerCase().includes('url') &&
- addon.options[option.id] &&
- ((isValueEncrypted(addon.options[option.id]) &&
- environment === 'server') ||
- !isValueEncrypted(addon.options[option.id]))
- ) {
- const url = parseAndDecryptString(addon.options[option.id] ?? '');
- if (url === null) {
- return createResponse(
- false,
- 'decryptionFailed',
- `Failed to decrypt URL for ${option.label}`
- );
- } else if (url === '') {
- return createResponse(
- false,
- 'emptyDecryption',
- `Decrypted URL for ${option.label} is empty`
- );
- }
- if (
- Settings.DISABLE_TORRENTIO &&
- url.match(/torrentio\.strem\.fun/) !== null
- ) {
- // if torrentio is disabled, don't allow the user to set URLs with torrentio.strem.fun
- return createResponse(
- false,
- 'torrentioDisabled',
- Settings.DISABLE_TORRENTIO_MESSAGE
- );
- } else if (
- Settings.DISABLE_TORRENTIO &&
- url.match(/stremthru\.elfhosted\.com/) !== null
- ) {
- // if torrentio is disabled, we need to inspect the stremthru URL to see if it's using torrentio
- try {
- const parsedUrl = new URL(url);
- // get the component before manifest.json
- const pathComponents = parsedUrl.pathname.split('/');
- if (pathComponents.includes('manifest.json')) {
- const index = pathComponents.indexOf('manifest.json');
- const componentBeforeManifest = pathComponents[index - 1];
- // base64 decode the component before manifest.json
- const decodedComponent = atob(componentBeforeManifest);
- const stremthruData = JSON.parse(decodedComponent);
- if (stremthruData?.manifest_url?.match(/torrentio.strem.fun/)) {
- return createResponse(
- false,
- 'torrentioDisabled',
- Settings.DISABLE_TORRENTIO_MESSAGE
- );
- }
- }
- } catch (_) {
- // ignore
- }
- } else {
- try {
- new URL(url);
- } catch (_) {
- return createResponse(
- false,
- 'invalidUrl',
- ` Invalid URL for ${option.label}`
- );
- }
- }
- }
-
- if (option.type === 'number' && addon.options[option.id]) {
- const input = addon.options[option.id];
- if (input !== undefined && !parseInt(input)) {
- return createResponse(
- false,
- 'invalidNumber',
- `${option.label} must be a number`
- );
- } else if (input !== undefined) {
- const value = parseInt(input);
- const { min, max } = option.constraints || {};
- if (
- (min !== undefined && value < min) ||
- (max !== undefined && value > max)
- ) {
- return createResponse(
- false,
- 'invalidNumber',
- `${option.label} must be between ${min} and ${max}`
- );
- }
- }
- }
- }
- }
- }
-
- if (!allowedFormatters.includes(config.formatter)) {
- if (config.formatter.startsWith('custom') && config.formatter.length > 7) {
- const jsonString = config.formatter.slice(7);
- const data = JSON.parse(jsonString);
- if (!data.name || !data.description) {
- return createResponse(
- false,
- 'invalidCustomFormatter',
- 'Invalid custom formatter: name and description are required'
- );
- }
- } else {
- return createResponse(
- false,
- 'invalidFormatter',
- `Invalid formatter: ${config.formatter}`
- );
- }
- }
- for (const service of config.services) {
- if (service.enabled) {
- const serviceDetail = serviceDetails.find(
- (detail) => detail.id === service.id
- );
- if (!serviceDetail) {
- return createResponse(
- false,
- 'invalidService',
- `Invalid service: ${service.id}`
- );
- }
- for (const credential of serviceDetail.credentials) {
- if (!service.credentials[credential.id]) {
- return createResponse(
- false,
- 'missingCredential',
- `${credential.label} is required for ${service.name}`
- );
- }
- }
- }
- }
-
- // need at least one visual tag, resolution, quality
-
- if (
- !config.visualTags.some((tag) => Object.values(tag)[0]) ||
- !config.resolutions.some((resolution) => Object.values(resolution)[0]) ||
- !config.qualities.some((quality) => Object.values(quality)[0])
- ) {
- return createResponse(
- false,
- 'noFilters',
- 'At least one visual tag, resolution, and quality must be selected'
- );
- }
-
- for (const [min, max] of [
- [config.minMovieSize, config.maxMovieSize],
- [config.minEpisodeSize, config.maxEpisodeSize],
- [config.minSize, config.maxSize],
- ]) {
- if (min && max) {
- if (min >= max) {
- return createResponse(
- false,
- 'invalidSizeRange',
- "Your minimum size limit can't be greater than or equal to your maximum size limit"
- );
- }
- }
- }
-
- if (config.maxResultsPerResolution && config.maxResultsPerResolution < 1) {
- return createResponse(
- false,
- 'invalidMaxResultsPerResolution',
- 'Max results per resolution must be greater than 0'
- );
- }
-
- if (
- config.mediaFlowConfig?.mediaFlowEnabled &&
- config.stremThruConfig?.stremThruEnabled
- ) {
- return createResponse(
- false,
- 'multipleProxyServices',
- 'Multiple proxy services are not allowed'
- );
- }
- if (config.mediaFlowConfig?.mediaFlowEnabled) {
- if (!config.mediaFlowConfig.proxyUrl) {
- return createResponse(
- false,
- 'missingProxyUrl',
- 'Proxy URL is required if MediaFlow is enabled'
- );
- }
- if (!config.mediaFlowConfig.apiPassword) {
- return createResponse(
- false,
- 'missingApiPassword',
- 'API Password is required if MediaFlow is enabled'
- );
- }
- }
-
- if (config.stremThruConfig?.stremThruEnabled) {
- if (!config.stremThruConfig.url) {
- return createResponse(
- false,
- 'missingUrl',
- 'URL is required if Stremthru is enabled'
- );
- }
- if (!config.stremThruConfig.credential) {
- return createResponse(
- false,
- 'missingCredential',
- 'Credential is required if StremThru is enabled'
- );
- }
- }
-
- if (
- (config.excludeFilters?.length ?? 0) > Settings.MAX_KEYWORD_FILTERS ||
- (config.strictIncludeFilters?.length ?? 0) > Settings.MAX_KEYWORD_FILTERS
- ) {
- return createResponse(
- false,
- 'tooManyFilters',
- `You can only have a maximum of ${Settings.MAX_KEYWORD_FILTERS} filters`
- );
- }
-
- const filters = [
- ...(config.excludeFilters || []),
- ...(config.strictIncludeFilters || []),
- ];
- filters.forEach((filter) => {
- if (filter.length > 20) {
- return createResponse(
- false,
- 'invalidFilter',
- 'One of your filters is too long'
- );
- }
- if (!filter) {
- return createResponse(
- false,
- 'invalidFilter',
- 'Filters must not be empty'
- );
- }
- });
-
- if (config.regexFilters) {
- if (!config.apiKey) {
- return createResponse(
- false,
- 'missingApiKey',
- 'Regex filtering requires an API key to be set'
- );
- }
-
- if (config.regexFilters.excludePattern) {
- try {
- new RegExp(config.regexFilters.excludePattern);
- } catch (e) {
- return createResponse(
- false,
- 'invalidExcludeRegex',
- 'Invalid exclude regex pattern'
- );
- }
- }
-
- if (config.regexFilters.includePattern) {
- try {
- new RegExp(config.regexFilters.includePattern);
- } catch (e) {
- return createResponse(
- false,
- 'invalidIncludeRegex',
- 'Invalid include regex pattern'
- );
- }
- }
- }
-
- if (config.regexSortPatterns) {
- if (!config.apiKey) {
- return createResponse(
- false,
- 'missingApiKey',
- 'Regex sorting requires an API key to be set'
- );
- }
-
- // Split the pattern by spaces and validate each one
- const patterns = config.regexSortPatterns.split(/\s+/).filter(Boolean);
- // Enforce an upper bound on the number of patterns
- if (patterns.length > Settings.MAX_REGEX_SORT_PATTERNS) {
- return createResponse(
- false,
- 'tooManyRegexSortPatterns',
- `You can specify at most ${Settings.MAX_REGEX_SORT_PATTERNS} regex sort patterns`
- );
- }
-
- for (const pattern of patterns) {
- const delimiter = '<::>';
- const delimiterIndex = pattern.indexOf(delimiter);
- let name: string = 'Unamed';
- let regexPattern = pattern;
- if (delimiterIndex !== -1) {
- name = pattern.slice(0, delimiterIndex).replace(/_/g, ' ');
- regexPattern = pattern.slice(delimiterIndex + delimiter.length);
- }
- try {
- new RegExp(regexPattern);
- } catch (e) {
- return createResponse(
- false,
- 'invalidRegexSortPattern',
- `Invalid regex sort pattern: ${name ? `"${name}" ` : ''}${regexPattern}`
- );
- }
- }
- }
- return createResponse(true, null, null);
-}
diff --git a/packages/addon/src/index.ts b/packages/addon/src/index.ts
deleted file mode 100644
index 21d564cb..00000000
--- a/packages/addon/src/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export * from './addon';
-export * from './config';
-export * from './manifest';
-export * from './responses';
diff --git a/packages/addon/src/manifest.ts b/packages/addon/src/manifest.ts
deleted file mode 100644
index 4c828b60..00000000
--- a/packages/addon/src/manifest.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { Config } from '@aiostreams/types';
-import { version, description } from '../../../package.json';
-import { getTextHash, Settings } from '@aiostreams/utils';
-
-const manifest = (config?: Config, configPresent?: boolean) => {
- let addonId = Settings.ADDON_ID;
- if (config && Settings.DETERMINISTIC_ADDON_ID) {
- addonId =
- addonId += `.${getTextHash(JSON.stringify(config)).substring(0, 12)}`;
- }
- return {
- name: config?.overrideName || Settings.ADDON_NAME,
- id: addonId,
- version: version,
- description: description,
- catalogs: [],
- resources: ['stream'],
- background:
- 'https://raw.githubusercontent.com/Viren070/AIOStreams/refs/heads/main/packages/frontend/public/assets/background.png',
- logo: 'https://raw.githubusercontent.com/Viren070/AIOStreams/refs/heads/main/packages/frontend/public/assets/logo.png',
- types: ['movie', 'series'],
- behaviorHints: {
- configurable: true,
- configurationRequired: config || configPresent ? false : true,
- },
- stremioAddonsConfig:
- Settings.STREMIO_ADDONS_CONFIG_ISSUER &&
- Settings.STREMIO_ADDONS_CONFIG_SIGNATURE
- ? {
- issuer: Settings.STREMIO_ADDONS_CONFIG_ISSUER,
- signature: Settings.STREMIO_ADDONS_CONFIG_SIGNATURE,
- }
- : undefined,
- };
-};
-
-export default manifest;
diff --git a/packages/addon/src/responses.ts b/packages/addon/src/responses.ts
deleted file mode 100644
index dc604ae0..00000000
--- a/packages/addon/src/responses.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { Settings } from '@aiostreams/utils';
-
-export const errorResponse = (
- errorMessage: string,
- origin?: string,
- path?: string,
- externalUrl?: string
-) => {
- return {
- streams: [errorStream(errorMessage, 'Error', origin, path, externalUrl)],
- };
-};
-
-export const errorStream = (
- errorMessage: string,
- errorTitle?: string,
- origin?: string,
- path?: string,
- externalUrl?: string
-) => {
- return {
- externalUrl:
- (origin && path ? origin + path : undefined) ||
- externalUrl ||
- 'https://github.com/Viren070/AIOStreams',
- name: `[❌] ${Settings.ADDON_NAME}\n${errorTitle || 'Error'}`,
- description: errorMessage,
- };
-};
diff --git a/packages/addon/src/server.ts b/packages/addon/src/server.ts
deleted file mode 100644
index e67cfa85..00000000
--- a/packages/addon/src/server.ts
+++ /dev/null
@@ -1,645 +0,0 @@
-import express, { Request, Response } from 'express';
-
-import path from 'path';
-import { AIOStreams } from './addon';
-import { Config, StreamRequest } from '@aiostreams/types';
-import { validateConfig } from './config';
-import manifest from './manifest';
-import { errorResponse } from './responses';
-import {
- Settings,
- addonDetails,
- parseAndDecryptString,
- Cache,
- unminifyConfig,
- minifyConfig,
- crushJson,
- compressData,
- encryptData,
- decompressData,
- decryptData,
- uncrushJson,
- loadSecretKey,
- createLogger,
- getTimeTakenSincePoint,
- isValueEncrypted,
- maskSensitiveInfo,
-} from '@aiostreams/utils';
-
-const logger = createLogger('server');
-
-const app = express();
-//logger.info(`Starting server and loading settings...`);
-logger.info('Starting server and loading settings...', { func: 'init' });
-Object.entries(Settings).forEach(([key, value]) => {
- switch (key) {
- case 'SECRET_KEY':
- if (value) {
- logger.info(`${key} = ${value.replace(/./g, '*').slice(0, 64)}`);
- }
- break;
-
- case 'BRANDING':
- case 'CUSTOM_CONFIGS':
- // Skip CUSTOM_CONFIGS processing here, handled later
- break;
-
- default:
- logger.info(`${key} = ${value}`);
- }
-});
-
-// attempt to load the secret key
-try {
- if (Settings.SECRET_KEY) loadSecretKey(true);
-} catch (error: any) {
- // determine command to run based on system OS
- const command =
- process.platform === 'win32'
- ? '[System.Guid]::NewGuid().ToString("N").Substring(0, 32) + [System.Guid]::NewGuid().ToString("N").Substring(0, 32)'
- : 'openssl rand -hex 32';
- logger.error(
- `The secret key is invalid. You will not be able to generate configurations. You can generate a new secret key by running the following command\n${command}`
- );
-}
-
-// Built-in middleware for parsing JSON
-app.use(express.json());
-// Built-in middleware for parsing URL-encoded data
-app.use(express.urlencoded({ extended: true }));
-
-// unhandled errors
-app.use((err: any, req: Request, res: Response, next: any) => {
- logger.error(`${err.message}`);
- res.status(500).send('Internal server error');
-});
-
-app.use((req, res, next) => {
- res.append('Access-Control-Allow-Origin', '*');
- res.append('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
- const start = Date.now();
- res.on('finish', () => {
- logger.info(
- `${req.method} ${req.path
- .replace(/\/ey[JI][\w\=]+/g, '/*******')
- .replace(
- /\/(E2?|B)?-[\w-\%]+/g,
- '/*******'
- )} - ${getIp(req) ? maskSensitiveInfo(getIp(req)!) : 'Unknown IP'} - ${res.statusCode} - ${getTimeTakenSincePoint(start)}`
- );
- });
- next();
-});
-
-app.get('/', (req, res) => {
- res.redirect('/configure');
-});
-
-app.get(
- ['/_next/*', '/assets/*', '/icon.ico', '/configure.txt'],
- (req, res) => {
- res.sendFile(path.join(__dirname, '../../frontend/out', req.path));
- }
-);
-
-if (!Settings.DISABLE_CUSTOM_CONFIG_GENERATOR_ROUTE) {
- app.get('/custom-config-generator', (req, res) => {
- res.sendFile(
- path.join(__dirname, '../../frontend/out/custom-config-generator.html')
- );
- });
-}
-
-app.get('/configure', (req, res) => {
- res.sendFile(path.join(__dirname, '../../frontend/out/configure.html'));
-});
-
-app.get('/:config/configure', (req, res) => {
- const config = req.params.config;
- if (config.startsWith('eyJ') || config.startsWith('eyI')) {
- return res.sendFile(
- path.join(__dirname, '../../frontend/out/configure.html')
- );
- }
- try {
- let configJson = extractJsonConfig(config);
- let configString = config;
- if (Settings.CUSTOM_CONFIGS) {
- const customConfig = extractCustomConfig(config);
- if (customConfig) {
- configJson = customConfig;
- configString = decodeURIComponent(Settings.CUSTOM_CONFIGS[config]);
- }
- }
- if (isValueEncrypted(configString)) {
- logger.info(`Encrypted config detected, encrypting credentials`);
- configJson = encryptInfoInConfig(configJson);
- }
- const base64Config = Buffer.from(JSON.stringify(configJson)).toString(
- 'base64'
- );
- res.redirect(`/${encodeURIComponent(base64Config)}/configure`);
- } catch (error: any) {
- logger.error(`Failed to extract config: ${error.message}`);
- res.status(400).send('Invalid config');
- }
-});
-
-app.get('/manifest.json', (req, res) => {
- res.status(200).json(manifest());
-});
-
-app.get('/:config/manifest.json', (req, res) => {
- const config = decodeURIComponent(req.params.config);
- let configJson: Config;
- try {
- configJson = extractJsonConfig(config);
- logger.info(`Extracted config for manifest request`);
- configJson = decryptEncryptedInfoFromConfig(configJson);
- if (Settings.LOG_SENSITIVE_INFO) {
- logger.info(`Final config: ${JSON.stringify(configJson)}`);
- }
- logger.info(`Successfully removed or decrypted sensitive info`);
- const { valid, errorMessage } = validateConfig(configJson);
- if (!valid) {
- logger.error(
- `Received invalid config for manifest request: ${errorMessage}`
- );
- res.status(400).json({ error: 'Invalid config', message: errorMessage });
- return;
- }
- } catch (error: any) {
- logger.error(`Failed to extract config: ${error.message}`);
- res.status(400).json({ error: 'Invalid config' });
- return;
- }
- res.status(200).json(manifest(configJson));
-});
-
-// Route for /stream
-app.get('/stream/:type/:id', (req: Request, res: Response) => {
- res
- .status(200)
- .json(
- errorResponse(
- 'You must configure this addon to use it',
- rootUrl(req),
- '/configure'
- )
- );
-});
-
-app.get('/:config/stream/:type/:id.json', (req, res: Response): void => {
- const { config, type, id } = req.params;
- let configJson: Config;
- try {
- configJson = extractJsonConfig(config);
- logger.info(`Extracted config for stream request`);
- configJson = decryptEncryptedInfoFromConfig(configJson);
- if (Settings.LOG_SENSITIVE_INFO) {
- logger.info(`Final config: ${JSON.stringify(configJson)}`);
- }
- logger.info(`Successfully removed or decrypted sensitive info`);
- } catch (error: any) {
- logger.error(`Failed to extract config: ${error.message}`);
- res.json(
- errorResponse(
- `${error.message}, please check the logs or click this stream to create an issue on GitHub`,
- rootUrl(req),
- undefined,
- 'https://github.com/Viren070/AIOStreams/issues/new?template=bug_report.yml'
- )
- );
- return;
- }
-
- logger.info(`Requesting streams for ${type} ${id}`);
-
- if (type !== 'movie' && type !== 'series') {
- logger.error(`Invalid type for stream request`);
- res.json(
- errorResponse(
- 'Invalid type for stream request, must be movie or series',
- rootUrl(req),
- '/'
- )
- );
- return;
- }
- let streamRequest: StreamRequest = { id, type };
-
- try {
- const { valid, errorCode, errorMessage } = validateConfig(configJson);
- if (!valid) {
- logger.error(`Received invalid config: ${errorCode} - ${errorMessage}`);
- res.json(
- errorResponse(errorMessage ?? 'Unknown', rootUrl(req), '/configure')
- );
- return;
- }
- configJson.requestingIp = getIp(req);
- const aioStreams = new AIOStreams(configJson);
- aioStreams
- .getStreams(streamRequest)
- .then((streams) => {
- res.json({ streams: streams });
- })
- .catch((error: any) => {
- logger.error(`Internal addon error: ${error.message}`);
- res.json(
- errorResponse(
- 'An unexpected error occurred, please check the logs or create an issue on GitHub',
- rootUrl(req),
- undefined,
- 'https://github.com/Viren070/AIOStreams/issues/new?template=bug_report.yml'
- )
- );
- });
- } catch (error: any) {
- logger.error(`Internal addon error: ${error.message}`);
- res.json(
- errorResponse(
- 'An unexpected error occurred, please check the logs or create an issue on GitHub',
- rootUrl(req),
- undefined,
- 'https://github.com/Viren070/AIOStreams/issues/new?template=bug_report.yml'
- )
- );
- }
-});
-
-app.post('/encrypt-user-data', (req, res) => {
- const { data } = req.body;
- let finalString: string = '';
- if (!data) {
- logger.error('/encrypt-user-data: No data provided');
- res.json({ success: false, message: 'No data provided' });
- return;
- }
- // First, validate the config
- try {
- const config = JSON.parse(data);
- const { valid, errorCode, errorMessage } = validateConfig(config);
- if (!valid) {
- logger.error(
- `generateConfig: Invalid config: ${errorCode} - ${errorMessage}`
- );
- res.json({ success: false, message: errorMessage, error: errorMessage });
- return;
- }
- } catch (error: any) {
- logger.error(`/encrypt-user-data: Invalid JSON: ${error.message}`);
- res.json({ success: false, message: 'Malformed configuration' });
- return;
- }
-
- try {
- const minified = minifyConfig(JSON.parse(data));
- const crushed = crushJson(JSON.stringify(minified));
- const compressed = compressData(crushed);
- if (!Settings.SECRET_KEY) {
- // use base64 encoding if no secret key is set
- finalString = `B-${encodeURIComponent(compressed.toString('base64'))}`;
- } else {
- const { iv, data } = encryptData(compressed);
- finalString = `E2-${encodeURIComponent(iv)}-${encodeURIComponent(data)}`;
- }
-
- logger.info(
- `|INF| server > /encrypt-user-data: Encrypted user data, compression report:`
- );
- logger.info(`+--------------------------------------------+`);
- logger.info(`| Original: ${data.length} bytes`);
- logger.info(`| URL Encoded: ${encodeURIComponent(data).length} bytes`);
- logger.info(`| Minified: ${JSON.stringify(minified).length} bytes`);
- logger.info(`| Crushed: ${crushed.length} bytes`);
- logger.info(`| Compressed: ${compressed.length} bytes`);
- logger.info(`| Final String: ${finalString.length} bytes`);
- logger.info(
- `| Ratio: ${((finalString.length / data.length) * 100).toFixed(2)}%`
- );
- logger.info(
- `| Reduction: ${data.length - finalString.length} bytes (${(((data.length - finalString.length) / data.length) * 100).toFixed(2)}%)`
- );
- logger.info(`+--------------------------------------------+`);
-
- res.json({ success: true, data: finalString });
- } catch (error: any) {
- logger.error(`/encrypt-user-data: ${error.message}`);
- logger.error(error);
- res.json({ success: false, message: error.message });
- }
-});
-
-app.get('/get-addon-config', (req, res) => {
- res.status(200).json({
- success: true,
- maxMovieSize: Settings.MAX_MOVIE_SIZE,
- maxEpisodeSize: Settings.MAX_EPISODE_SIZE,
- torrentioDisabled: Settings.DISABLE_TORRENTIO,
- apiKeyRequired: !!Settings.API_KEY,
- });
-});
-
-app.get('/health', (req, res) => {
- res.status(200).json({ status: 'ok' });
-});
-
-// define 404
-app.use((req, res) => {
- res.status(404).sendFile(path.join(__dirname, '../../frontend/out/404.html'));
-});
-
-app.listen(Settings.PORT, () => {
- logger.info(`Listening on port ${Settings.PORT}`);
-});
-
-function getIp(req: Request): string | undefined {
- return (
- req.get('X-Client-IP') ||
- req.get('X-Forwarded-For')?.split(',')[0].trim() ||
- req.get('X-Real-IP') ||
- req.get('CF-Connecting-IP') ||
- req.get('True-Client-IP') ||
- req.get('X-Forwarded')?.split(',')[0].trim() ||
- req.get('Forwarded-For')?.split(',')[0].trim() ||
- req.ip
- );
-}
-function extractJsonConfig(config: string): Config {
- if (
- config.startsWith('eyJ') ||
- config.startsWith('eyI') ||
- config.startsWith('B-') ||
- isValueEncrypted(config)
- ) {
- return extractEncryptedOrEncodedConfig(config, 'Config');
- }
- if (Settings.CUSTOM_CONFIGS) {
- const customConfig = extractCustomConfig(config);
- if (customConfig) return customConfig;
- }
- throw new Error('Config was in an unexpected format');
-}
-
-function extractCustomConfig(config: string): Config | undefined {
- const customConfig = Settings.CUSTOM_CONFIGS[config];
- if (!customConfig) return undefined;
- logger.info(
- `Found custom config for alias ${config}, attempting to extract config`
- );
- return extractEncryptedOrEncodedConfig(
- decodeURIComponent(customConfig),
- `CustomConfig ${config}`
- );
-}
-
-function extractEncryptedOrEncodedConfig(
- config: string,
- label: string
-): Config {
- let decodedConfig: Config;
- try {
- if (config.startsWith('E-')) {
- // compressed and encrypted (hex)
- logger.info(`Extracting encrypted (v1) config`);
- const parts = config.split('-');
- if (parts.length !== 3) {
- throw new Error('Invalid encrypted config format');
- }
- const iv = Buffer.from(decodeURIComponent(parts[1]), 'hex');
- const data = Buffer.from(decodeURIComponent(parts[2]), 'hex');
- decodedConfig = JSON.parse(decompressData(decryptData(data, iv)));
- } else if (config.startsWith('E2-')) {
- // minified, crushed, compressed and encrypted (base64)
- logger.info(`Extracting encrypted (v2) config`);
- const parts = config.split('-');
- if (parts.length !== 3) {
- throw new Error('Invalid encrypted config format');
- }
- const iv = Buffer.from(decodeURIComponent(parts[1]), 'base64');
- const data = Buffer.from(decodeURIComponent(parts[2]), 'base64');
- const compressedCrushedJson = decryptData(data, iv);
- const crushedJson = decompressData(compressedCrushedJson);
- const minifiedConfig = uncrushJson(crushedJson);
- decodedConfig = unminifyConfig(JSON.parse(minifiedConfig));
- } else if (config.startsWith('B-')) {
- // minifed, crushed, compressed, base64 encoded
- logger.info(`Extracting base64 encoded and compressed config`);
- decodedConfig = unminifyConfig(
- JSON.parse(
- uncrushJson(decompressData(Buffer.from(config.slice(2), 'base64')))
- )
- );
- } else {
- // plain base64 encoded
- logger.info(`Extracting plain base64 encoded config`);
- decodedConfig = JSON.parse(
- Buffer.from(config, 'base64').toString('utf-8')
- );
- }
- return decodedConfig;
- } catch (error: any) {
- logger.error(`Failed to parse ${label}: ${error.message}`, {
- func: 'extractJsonConfig',
- });
- logger.error(error, { func: 'extractJsonConfig' });
- throw new Error(`Failed to parse ${label}`);
- }
-}
-
-function decryptEncryptedInfoFromConfig(config: Config): Config {
- if (config.services) {
- config.services.forEach(
- (service) =>
- service.credentials &&
- processObjectValues(
- service.credentials,
- `service ${service.id}`,
- true,
- (key, value) => isValueEncrypted(value)
- )
- );
- }
-
- if (config.mediaFlowConfig) {
- decryptMediaFlowConfig(config.mediaFlowConfig);
- }
- if (config.stremThruConfig) {
- decryptStremThruConfig(config.stremThruConfig);
- }
-
- if (config.apiKey) {
- config.apiKey = decryptValue(config.apiKey, 'aioStreams apiKey');
- }
-
- if (config.addons) {
- config.addons.forEach((addon) => {
- if (addon.options) {
- processObjectValues(
- addon.options,
- `addon ${addon.id}`,
- true,
- (key, value) =>
- isValueEncrypted(value) &&
- // Decrypt only if the option is secret
- (
- addonDetails.find((addonDetail) => addonDetail.id === addon.id)
- ?.options ?? []
- ).some((option) => option.id === key && option.secret)
- );
- }
- });
- }
- return config;
-}
-
-function decryptMediaFlowConfig(mediaFlowConfig: {
- apiPassword: string;
- proxyUrl: string;
- publicIp: string;
-}): void {
- const { apiPassword, proxyUrl, publicIp } = mediaFlowConfig;
- mediaFlowConfig.apiPassword = decryptValue(
- apiPassword,
- 'MediaFlow apiPassword'
- );
- mediaFlowConfig.proxyUrl = decryptValue(proxyUrl, 'MediaFlow proxyUrl');
- mediaFlowConfig.publicIp = decryptValue(publicIp, 'MediaFlow publicIp');
-}
-
-function decryptStremThruConfig(
- stremThruConfig: Config['stremThruConfig']
-): void {
- if (!stremThruConfig) return;
- const { url, credential, publicIp } = stremThruConfig;
- stremThruConfig.url = decryptValue(url, 'StremThru url');
- stremThruConfig.credential = decryptValue(credential, 'StremThru credential');
- stremThruConfig.publicIp = decryptValue(publicIp, 'StremThru publicIp');
-}
-
-function encryptInfoInConfig(config: Config): Config {
- if (config.services) {
- config.services.forEach(
- (service) =>
- service.credentials &&
- processObjectValues(
- service.credentials,
- `service ${service.id}`,
- false,
- () => true
- )
- );
- }
-
- if (config.mediaFlowConfig) {
- encryptMediaFlowConfig(config.mediaFlowConfig);
- }
-
- if (config.stremThruConfig) {
- encryptStremThruConfig(config.stremThruConfig);
- }
-
- if (config.apiKey) {
- // we can either remove the api key for better security or encrypt it for usability
- // removing it means the user has to enter it every time upon reconfiguration.
- config.apiKey = encryptValue(config.apiKey, 'aioStreams apiKey');
- }
-
- if (config.addons) {
- config.addons.forEach((addon) => {
- if (addon.options) {
- processObjectValues(
- addon.options,
- `addon ${addon.id}`,
- false,
- (key) => {
- const addonDetail = addonDetails.find(
- (addonDetail) => addonDetail.id === addon.id
- );
- if (!addonDetail) return false;
- const optionDetail = addonDetail.options?.find(
- (option) => option.id === key
- );
- // Encrypt only if the option is secret
- return optionDetail?.secret ?? false;
- }
- );
- }
- });
- }
- return config;
-}
-
-function encryptMediaFlowConfig(mediaFlowConfig: {
- apiPassword: string;
- proxyUrl: string;
- publicIp: string;
-}): void {
- const { apiPassword, proxyUrl, publicIp } = mediaFlowConfig;
- mediaFlowConfig.apiPassword = encryptValue(
- apiPassword,
- 'MediaFlow apiPassword'
- );
- mediaFlowConfig.proxyUrl = encryptValue(proxyUrl, 'MediaFlow proxyUrl');
- mediaFlowConfig.publicIp = encryptValue(publicIp, 'MediaFlow publicIp');
-}
-
-function encryptStremThruConfig(
- stremThruConfig: Config['stremThruConfig']
-): void {
- if (!stremThruConfig) return;
- const { url, credential, publicIp } = stremThruConfig;
- stremThruConfig.url = encryptValue(url, 'StremThru url');
- stremThruConfig.credential = encryptValue(credential, 'StremThru credential');
- stremThruConfig.publicIp = encryptValue(publicIp, 'StremThru publicIp');
-}
-
-function processObjectValues(
- obj: Record,
- labelPrefix: string,
- decrypt: boolean,
- condition: (key: string, value: any) => boolean
-): void {
- Object.keys(obj).forEach((key) => {
- const value = obj[key];
- if (condition(key, value)) {
- logger.debug(`Processing ${labelPrefix} ${key}`);
- obj[key] = decrypt
- ? decryptValue(value, `${labelPrefix} ${key}`)
- : encryptValue(value, `${labelPrefix} ${key}`);
- }
- });
-}
-
-function encryptValue(value: any, label: string): any {
- if (value && !isValueEncrypted(value)) {
- try {
- const { iv, data } = encryptData(compressData(value));
- return `E2-${iv}-${data}`;
- } catch (error: any) {
- logger.error(`Failed to encrypt ${label}`, { func: 'encryptValue' });
- logger.error(error, { func: 'encryptValue' });
- return '';
- }
- }
- return value;
-}
-
-function decryptValue(value: any, label: string): any {
- try {
- if (!isValueEncrypted(value)) return value;
- const decrypted = parseAndDecryptString(value);
- if (decrypted === null) throw new Error('Decryption failed');
- return decrypted;
- } catch (error: any) {
- logger.error(`Failed to decrypt ${label}: ${error.message}`, {
- func: 'decryptValue',
- });
- logger.error(error, { func: 'decryptValue' });
- throw new Error('Failed to decrypt config');
- }
-}
-
-const rootUrl = (req: Request) =>
- `${req.protocol}://${req.hostname}${req.hostname === 'localhost' ? `:${Settings.PORT}` : ''}`;
diff --git a/packages/addon/tsconfig.json b/packages/addon/tsconfig.json
deleted file mode 100644
index ea109a6b..00000000
--- a/packages/addon/tsconfig.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "extends": "../../tsconfig.base.json",
- "compilerOptions": {
- "rootDir": "src",
- "outDir": "dist",
- "resolveJsonModule": true
- },
- "references": [
- {
- "path": "../wrappers"
- },
- {
- "path": "../formatters"
- },
- {
- "path": "../types"
- },
- {
- "path": "../utils"
- }
- ]
-}
diff --git a/packages/cloudflare-worker/package.json b/packages/cloudflare-worker/package.json
deleted file mode 100644
index bdf209ce..00000000
--- a/packages/cloudflare-worker/package.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "@aiostreams/cloudflare-worker",
- "version": "1.21.1",
- "scripts": {
- "deploy": "wrangler deploy",
- "dev": "wrangler dev",
- "start": "wrangler dev",
- "test": "vitest",
- "cf-typegen": "wrangler types"
- },
- "dependencies": {
- "@aiostreams/addon": "^1.0.0",
- "@aiostreams/types": "^1.0.0"
- },
- "devDependencies": {
- "@cloudflare/workers-types": "^4.20241224.0",
- "typescript": "^5.5.2",
- "wrangler": "^3.99.0"
- }
-}
diff --git a/packages/cloudflare-worker/src/index.ts b/packages/cloudflare-worker/src/index.ts
deleted file mode 100644
index 254a9f68..00000000
--- a/packages/cloudflare-worker/src/index.ts
+++ /dev/null
@@ -1,171 +0,0 @@
-import { AIOStreams, errorResponse, validateConfig } from '@aiostreams/addon';
-import manifest from '@aiostreams/addon/src/manifest';
-import { Config, StreamRequest } from '@aiostreams/types';
-import { Cache, unminifyConfig } from '@aiostreams/utils';
-
-const HEADERS = {
- 'Access-Control-Allow-Origin': '*',
- 'Access-Control-Allow-Methods': 'GET,HEAD,POST,OPTIONS',
-};
-
-function createJsonResponse(data: any): Response {
- return new Response(JSON.stringify(data, null, 4), {
- headers: HEADERS,
- });
-}
-
-function createResponse(message: string, status: number): Response {
- return new Response(message, {
- status,
- headers: HEADERS,
- });
-}
-
-export default {
- async fetch(request, env, ctx): Promise {
- try {
- const url = new URL(decodeURIComponent(request.url));
- const components = url.pathname.split('/').splice(1);
-
- // handle static asset requests
- if (components.includes('_next') || components.includes('assets')) {
- return env.ASSETS.fetch(request);
- }
-
- if (url.pathname === '/icon.ico') {
- return env.ASSETS.fetch(request);
- }
-
- // redirect to /configure if root path is requested
- if (url.pathname === '/') {
- return Response.redirect(url.origin + '/configure', 301);
- }
-
- // handle /encrypt-user-data POST requests
- if (components.includes('encrypt-user-data')) {
- const data = (await request.json()) as { data: string };
- if (!data) {
- return createResponse('Invalid Request', 400);
- }
- const dataToEncode = data.data;
- try {
- console.log(
- `Received /encrypt-user-data request with Data: ${dataToEncode}`
- );
- const encodedData = Buffer.from(dataToEncode).toString('base64');
- return createJsonResponse({ data: encodedData, success: true });
- } catch (error: any) {
- console.error(error);
- return createJsonResponse({ error: error.message, success: false });
- }
- }
- // handle /configure and /:config/configure requests
- if (components.includes('configure')) {
- if (components.length === 1) {
- return env.ASSETS.fetch(request);
- } else {
- // display configure page with config still in url
- return env.ASSETS.fetch(
- new Request(url.origin + '/configure', request)
- );
- }
- }
-
- // handle /manifest.json and /:config/manifest.json requests
- if (components.includes('manifest.json')) {
- if (components.length === 1) {
- return createJsonResponse(manifest());
- } else {
- return createJsonResponse(manifest(undefined, true));
- }
- }
-
- if (components.includes('stream')) {
- // when /stream is requested without config
- let config = decodeURIComponent(components[0]);
- console.log(`components: ${components}`);
- if (components.length < 4) {
- return createJsonResponse(
- errorResponse(
- 'You must configure this addon first',
- url.origin,
- '/configure'
- )
- );
- }
- console.log(`Received /stream request with Config: ${config}`);
- const decodedPath = decodeURIComponent(url.pathname);
-
- const streamMatch = /stream\/(movie|series)\/([^/]+)\.json/.exec(
- decodedPath
- );
- if (!streamMatch) {
- let path = decodedPath.replace(`/${config}`, '');
- console.error(`Invalid request: ${path}`);
- return createResponse('Invalid request', 400);
- }
-
- const [type, id] = streamMatch.slice(1);
- console.log(`Received /stream request with Type: ${type}, ID: ${id}`);
-
- let decodedConfig: Config;
-
- if (config.startsWith('E-') || config.startsWith('E2-')) {
- return createResponse('Encrypted Config Not Supported', 400);
- }
- try {
- decodedConfig = unminifyConfig(
- JSON.parse(Buffer.from(config, 'base64').toString('utf-8'))
- );
- } catch (error: any) {
- console.error(error);
- return createJsonResponse(
- errorResponse(
- 'Unable to parse config, please reconfigure or create an issue on GitHub',
- url.origin,
- '/configure'
- )
- );
- }
- const { valid, errorMessage, errorCode } =
- validateConfig(decodedConfig);
- if (!valid) {
- console.error(`Invalid config: ${errorMessage}`);
- return createJsonResponse(
- errorResponse(errorMessage ?? 'Unknown', url.origin, '/configure')
- );
- }
-
- if (type !== 'movie' && type !== 'series') {
- return createResponse('Invalid Request', 400);
- }
-
- let streamRequest: StreamRequest = { id, type };
-
- decodedConfig.requestingIp =
- request.headers.get('X-Forwarded-For') ||
- request.headers.get('X-Real-IP') ||
- request.headers.get('CF-Connecting-IP') ||
- request.headers.get('X-Client-IP') ||
- undefined;
-
- const aioStreams = new AIOStreams(decodedConfig);
- const streams = await aioStreams.getStreams(streamRequest);
- return createJsonResponse({ streams });
- }
-
- const notFound = await env.ASSETS.fetch(
- new Request(url.origin + '/404', request)
- );
- return new Response(notFound.body, { ...notFound, status: 404 });
- } catch (e) {
- console.error(e);
- return new Response('Internal Server Error', {
- status: 500,
- headers: {
- 'Content-Type': 'text/plain',
- },
- });
- }
- },
-} satisfies ExportedHandler;
diff --git a/packages/cloudflare-worker/tsconfig.json b/packages/cloudflare-worker/tsconfig.json
deleted file mode 100644
index e006935d..00000000
--- a/packages/cloudflare-worker/tsconfig.json
+++ /dev/null
@@ -1,48 +0,0 @@
-{
- "compilerOptions": {
- "target": "es2021",
- "lib": ["es2021"],
- /* Specify what JSX code is generated. */
- "jsx": "react-jsx",
-
- /* Specify what module code is generated. */
- "module": "es2022",
- /* Specify how TypeScript looks up a file from a given module specifier. */
- "moduleResolution": "Bundler",
- /* Specify type package names to be included without being referenced in a source file. */
- "types": ["@cloudflare/workers-types"],
- /* Enable importing .json files */
- "resolveJsonModule": true,
-
- /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
- "allowJs": true,
- /* Enable error reporting in type-checked JavaScript files. */
- "checkJs": false,
-
- /* Disable emitting files from a compilation. */
- "noEmit": true,
-
- /* Ensure that each file can be safely transpiled without relying on other imports. */
- "isolatedModules": true,
- /* Allow 'import x from y' when a module doesn't have a default export. */
- "allowSyntheticDefaultImports": true,
- /* Ensure that casing is correct in imports. */
- "forceConsistentCasingInFileNames": true,
-
- /* Enable all strict type-checking options. */
- "strict": true,
-
- /* Skip type checking all .d.ts files. */
- "skipLibCheck": true
- },
- "references": [
- {
- "path": "../addon"
- },
- {
- "path": "../types"
- }
- ],
- "exclude": ["test"],
- "include": ["worker-configuration.d.ts", "src/**/*.ts"]
-}
diff --git a/packages/cloudflare-worker/worker-configuration.d.ts b/packages/cloudflare-worker/worker-configuration.d.ts
deleted file mode 100644
index 43fbb88a..00000000
--- a/packages/cloudflare-worker/worker-configuration.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-// Generated by Wrangler by running `wrangler types`
-
-interface Env {
- ASSETS: Fetcher;
-}
diff --git a/packages/cloudflare-worker/wrangler.toml b/packages/cloudflare-worker/wrangler.toml
deleted file mode 100644
index 16cca838..00000000
--- a/packages/cloudflare-worker/wrangler.toml
+++ /dev/null
@@ -1,115 +0,0 @@
-#:schema node_modules/wrangler/config-schema.json
-name = "aiostreams"
-main = "src/index.ts"
-compatibility_date = "2024-12-24"
-compatibility_flags = ["nodejs_compat"]
-assets = { directory = "../frontend/out", binding = "ASSETS", experimental_serve_directly = false}
-
-# Workers Logs
-# Docs: https://developers.cloudflare.com/workers/observability/logs/workers-logs/
-# Configuration: https://developers.cloudflare.com/workers/observability/logs/workers-logs/#enable-workers-logs
-[observability]
-enabled = true
-
-# Automatically place your workloads in an optimal location to minimize latency.
-# If you are running back-end logic in a Worker, running it closer to your back-end infrastructure
-# rather than the end user may result in better performance.
-# Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
-# [placement]
-# mode = "smart"
-
-# Variable bindings. These are arbitrary, plaintext strings (similar to environment variables)
-# Docs:
-# - https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
-# Note: Use secrets to store sensitive data.
-# - https://developers.cloudflare.com/workers/configuration/secrets/
-# [vars]
-# MY_VARIABLE = "production_value"
-
-# Bind the Workers AI model catalog. Run machine learning models, powered by serverless GPUs, on Cloudflare’s global network
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#workers-ai
-# [ai]
-# binding = "AI"
-
-# Bind an Analytics Engine dataset. Use Analytics Engine to write analytics within your Pages Function.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#analytics-engine-datasets
-# [[analytics_engine_datasets]]
-# binding = "MY_DATASET"
-
-# Bind a headless browser instance running on Cloudflare's global network.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#browser-rendering
-# [browser]
-# binding = "MY_BROWSER"
-
-# Bind a D1 database. D1 is Cloudflare’s native serverless SQL database.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#d1-databases
-# [[d1_databases]]
-# binding = "MY_DB"
-# database_name = "my-database"
-# database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
-
-# Bind a dispatch namespace. Use Workers for Platforms to deploy serverless functions programmatically on behalf of your customers.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#dispatch-namespace-bindings-workers-for-platforms
-# [[dispatch_namespaces]]
-# binding = "MY_DISPATCHER"
-# namespace = "my-namespace"
-
-# Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model.
-# Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects
-# [[durable_objects.bindings]]
-# name = "MY_DURABLE_OBJECT"
-# class_name = "MyDurableObject"
-
-# Durable Object migrations.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#migrations
-# [[migrations]]
-# tag = "v1"
-# new_classes = ["MyDurableObject"]
-
-# Bind a Hyperdrive configuration. Use to accelerate access to your existing databases from Cloudflare Workers.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#hyperdrive
-# [[hyperdrive]]
-# binding = "MY_HYPERDRIVE"
-# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
-
-# Bind a KV Namespace. Use KV as persistent storage for small key-value pairs.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#kv-namespaces
-# [[kv_namespaces]]
-# binding = "MY_KV_NAMESPACE"
-# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
-
-# Bind an mTLS certificate. Use to present a client certificate when communicating with another service.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#mtls-certificates
-# [[mtls_certificates]]
-# binding = "MY_CERTIFICATE"
-# certificate_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
-
-# Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#queues
-# [[queues.producers]]
-# binding = "MY_QUEUE"
-# queue = "my-queue"
-
-# Bind a Queue consumer. Queue Consumers can retrieve tasks scheduled by Producers to act on them.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#queues
-# [[queues.consumers]]
-# queue = "my-queue"
-
-# Bind an R2 Bucket. Use R2 to store arbitrarily large blobs of data, such as files.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#r2-buckets
-# [[r2_buckets]]
-# binding = "MY_BUCKET"
-# bucket_name = "my-bucket"
-
-# Bind another Worker service. Use this binding to call another Worker without network overhead.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings
-# [[services]]
-# binding = "MY_SERVICE"
-# service = "my-service"
-
-# Bind a Vectorize index. Use to store and query vector embeddings for semantic search, classification and other vector search use-cases.
-# Docs: https://developers.cloudflare.com/workers/wrangler/configuration/#vectorize-indexes
-# [[vectorize]]
-# binding = "MY_INDEX"
-# index_name = "my-index"
diff --git a/packages/core/package.json b/packages/core/package.json
new file mode 100644
index 00000000..0f8bbe7d
--- /dev/null
+++ b/packages/core/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "@aiostreams/core",
+ "version": "0.0.0",
+ "main": "dist/index.js",
+ "scripts": {
+ "test": "vitest run --passWithNoTests",
+ "test:watch": "vitest watch",
+ "build": "tsc"
+ },
+ "description": "Combine all your streams into one addon and display them with consistent formatting, sorting, and filtering.",
+ "dependencies": {
+ "bcrypt": "^6.0.0",
+ "dotenv": "^16.4.7",
+ "envalid": "^8.0.0",
+ "expr-eval": "^2.0.2",
+ "moment-timezone": "^0.5.48",
+ "parse-torrent-title": "github:TheBeastLT/parse-torrent-title",
+ "pg": "^8.16.0",
+ "sqlite": "^5.1.1",
+ "sqlite3": "^5.1.7",
+ "super-regex": "^1.0.0",
+ "undici": "^7.2.3",
+ "winston": "^3.17.0",
+ "zod": "^3.24.4"
+ },
+ "devDependencies": {
+ "@types/bcrypt": "^5.0.2",
+ "@types/node": "^20.14.10",
+ "@types/pg": "^8.15.2"
+ }
+}
diff --git a/packages/core/src/db/db.ts b/packages/core/src/db/db.ts
new file mode 100644
index 00000000..09ff4a3a
--- /dev/null
+++ b/packages/core/src/db/db.ts
@@ -0,0 +1,230 @@
+import { TABLES } from './schemas';
+import { createLogger } from '../utils';
+import { parseConnectionURI, adaptQuery, ConnectionURI } from './utils';
+
+const logger = createLogger('database');
+
+import { Pool, Client, QueryResult } from 'pg';
+import sqlite3 from 'sqlite3';
+import { open, Database } from 'sqlite';
+import { URL } from 'url';
+import path from 'path';
+import fs from 'fs';
+
+type QueryResultRow = Record;
+
+interface UnifiedQueryResult {
+ rows: T[];
+ rowCount: number;
+ command?: string;
+}
+
+type DBDialect = 'postgres' | 'sqlite';
+
+type DSNModifier = (url: URL, query: URLSearchParams) => void;
+
+type Transaction = {
+ commit: () => Promise;
+ rollback: () => Promise;
+ execute: (query: string, params?: any[]) => Promise>;
+};
+
+export class DB {
+ private static instance: DB;
+ private db!: Pool | Database;
+ private static initialised: boolean = false;
+ private static dialect: DBDialect;
+ private uri!: ConnectionURI;
+ private dsnModifiers: DSNModifier[] = [];
+
+ private constructor() {}
+
+ static getInstance(): DB {
+ if (!this.instance) {
+ this.instance = new DB();
+ }
+ return this.instance;
+ }
+ isInitialised(): boolean {
+ return DB.initialised;
+ }
+
+ getDialect(): DBDialect {
+ return DB.dialect;
+ }
+
+ async initialise(
+ uri: string,
+ dsnModifiers: DSNModifier[] = []
+ ): Promise {
+ if (DB.initialised) {
+ return;
+ }
+ try {
+ this.uri = parseConnectionURI(uri);
+ this.dsnModifiers = dsnModifiers;
+ await this.open();
+ await this.ping();
+
+ // create tables
+ for (const [name, schema] of Object.entries(TABLES)) {
+ const createTableQuery = `CREATE TABLE IF NOT EXISTS ${name} (${schema})`;
+ await this.execute(createTableQuery);
+ }
+
+ if (this.uri.dialect === 'sqlite') {
+ await this.execute('PRAGMA busy_timeout = 5000');
+ await this.execute('PRAGMA foreign_keys = ON');
+ await this.execute('PRAGMA synchronous = OFF');
+ await this.execute('PRAGMA journal_mode = WAL');
+ await this.execute('PRAGMA locking_mode = IMMEDIATE');
+ }
+
+ DB.initialised = true;
+ DB.dialect = this.uri.dialect;
+ } catch (error) {
+ logger.error('Failed to initialize database:', error);
+ throw error;
+ }
+ }
+
+ async open(): Promise {
+ if (this.uri.dialect === 'postgres') {
+ const pool = new Pool({
+ connectionString: this.uri.url.toString(),
+ idleTimeoutMillis: 30000,
+ connectionTimeoutMillis: 2000,
+ });
+ this.db = pool;
+ this.uri.dialect = 'postgres';
+ } else if (this.uri.dialect === 'sqlite') {
+ // make parent directory if it does not exist
+ const parentDir = path.dirname(this.uri.filename);
+ if (!parentDir) {
+ throw new Error('Invalid SQLite path');
+ }
+ if (!fs.existsSync(parentDir)) {
+ fs.mkdirSync(parentDir, { recursive: true });
+ }
+ logger.debug(`Opening SQLite database: ${this.uri.filename}`);
+
+ this.db = await open({
+ filename: this.uri.filename,
+ driver: sqlite3.Database,
+ });
+ this.uri.dialect = 'sqlite';
+ }
+ }
+
+ async close(): Promise {
+ if (this.uri.dialect === 'postgres') {
+ await (this.db as Pool).end();
+ } else if (this.uri.dialect === 'sqlite') {
+ await (this.db as Database).close();
+ }
+ }
+
+ async ping(): Promise {
+ if (this.uri.dialect === 'postgres') {
+ await (this.db as Pool).query('SELECT 1');
+ } else if (this.uri.dialect === 'sqlite') {
+ await (this.db as Database).get('SELECT 1');
+ }
+ }
+
+ async execute(query: string, params?: any[]): Promise {
+ if (this.uri.dialect === 'postgres') {
+ return (this.db as Pool).query(
+ adaptQuery(query, this.uri.dialect),
+ params
+ );
+ } else if (this.uri.dialect === 'sqlite') {
+ return (this.db as Database).run(
+ adaptQuery(query, this.uri.dialect),
+ params
+ );
+ }
+ throw new Error('Unsupported dialect');
+ }
+
+ async query(query: string, params?: any[]): Promise {
+ const adaptedQuery = adaptQuery(query, this.uri.dialect);
+ if (this.uri.dialect === 'postgres') {
+ const result = await (this.db as Pool).query(adaptedQuery, params);
+ return result.rows;
+ } else if (this.uri.dialect === 'sqlite') {
+ return (this.db as Database).all(adaptedQuery, params);
+ }
+ return [];
+ }
+
+ async begin(): Promise {
+ if (this.uri.dialect === 'postgres') {
+ const client = await (this.db as Pool).connect();
+ await client.query('BEGIN');
+
+ let finalised = false;
+
+ const finalise = () => {
+ if (!finalised) {
+ finalised = true;
+ client.release();
+ }
+ };
+
+ return {
+ commit: async () => {
+ try {
+ await client.query('COMMIT');
+ } finally {
+ finalise();
+ }
+ },
+ rollback: async () => {
+ try {
+ await client.query('ROLLBACK');
+ } finally {
+ finalise();
+ }
+ },
+ execute: async (
+ query: string,
+ params?: any[]
+ ): Promise => {
+ const result = await client.query(
+ adaptQuery(query, 'postgres'),
+ params
+ );
+ return {
+ rows: result.rows,
+ rowCount: result.rowCount || 0,
+ command: result.command,
+ };
+ },
+ };
+ } else if (this.uri.dialect === 'sqlite') {
+ const db = this.db as Database;
+ await db.run('BEGIN');
+ return {
+ commit: async () => {
+ await db.run('COMMIT');
+ },
+ rollback: async () => {
+ await db.run('ROLLBACK');
+ },
+ execute: async (
+ query: string,
+ params?: any[]
+ ): Promise => {
+ const result = await db.all(adaptQuery(query, 'sqlite'), params);
+ return {
+ rows: result,
+ rowCount: result.length || 0,
+ command: 'SELECT',
+ };
+ },
+ };
+ }
+ throw new Error('Unsupported transaction dialect');
+ }
+}
diff --git a/packages/core/src/db/index.ts b/packages/core/src/db/index.ts
new file mode 100644
index 00000000..efc8bdba
--- /dev/null
+++ b/packages/core/src/db/index.ts
@@ -0,0 +1,4 @@
+export * from './db';
+export * from './users';
+export * from './schemas';
+export * from './queue';
diff --git a/packages/core/src/db/queue.ts b/packages/core/src/db/queue.ts
new file mode 100644
index 00000000..f7b9cbfa
--- /dev/null
+++ b/packages/core/src/db/queue.ts
@@ -0,0 +1,58 @@
+import { createLogger } from '../utils';
+import { DB } from './db';
+const logger = createLogger('db');
+const db = DB.getInstance();
+
+// Queue for SQLite transactions
+
+export class TransactionQueue {
+ private queue: Array<() => Promise> = [];
+ private processing = false;
+ private static instance: TransactionQueue;
+
+ private constructor() {}
+
+ static getInstance(): TransactionQueue {
+ if (!this.instance) {
+ this.instance = new TransactionQueue();
+ }
+ return this.instance;
+ }
+
+ async enqueue(operation: () => Promise): Promise {
+ // If using PostgreSQL, execute directly without queuing
+ if (db['uri']?.dialect === 'postgres') {
+ return operation();
+ }
+
+ return new Promise((resolve, reject) => {
+ this.queue.push(async () => {
+ try {
+ const result = await operation();
+ resolve(result);
+ } catch (error) {
+ reject(error);
+ }
+ });
+ this.processQueue();
+ });
+ }
+
+ private async processQueue() {
+ if (this.processing || this.queue.length === 0) return;
+ this.processing = true;
+
+ while (this.queue.length > 0) {
+ const operation = this.queue.shift();
+ if (operation) {
+ try {
+ await operation();
+ } catch (error) {
+ logger.error('Error processing queued operation:', error);
+ }
+ }
+ }
+
+ this.processing = false;
+ }
+}
diff --git a/packages/core/src/db/schemas.ts b/packages/core/src/db/schemas.ts
new file mode 100644
index 00000000..31440af5
--- /dev/null
+++ b/packages/core/src/db/schemas.ts
@@ -0,0 +1,777 @@
+import { z } from 'zod';
+import * as constants from '../utils/constants';
+
+const ServiceIds = z.enum(constants.SERVICES);
+
+const Resolutions = z.enum(constants.RESOLUTIONS);
+
+const Qualities = z.enum(constants.QUALITIES);
+
+const VisualTags = z.enum(constants.VISUAL_TAGS);
+
+const AudioTags = z.enum(constants.AUDIO_TAGS);
+
+const AudioChannels = z.enum(constants.AUDIO_CHANNELS);
+
+const Encodes = z.enum(constants.ENCODES);
+
+// const SortCriteria = z.enum(constants.SORT_CRITERIA);
+
+// const SortDirections = z.enum(constants.SORT_DIRECTIONS);
+
+const SortCriterion = z.object({
+ key: z.enum(constants.SORT_CRITERIA),
+ direction: z.enum(constants.SORT_DIRECTIONS),
+});
+
+export type SortCriterion = z.infer;
+
+const StreamTypes = z.enum(constants.STREAM_TYPES);
+const Languages = z.enum(constants.LANGUAGES);
+
+const Formatter = z.object({
+ id: z.enum(constants.FORMATTERS),
+ definition: z
+ .object({
+ name: z.string().min(1),
+ description: z.string().min(1),
+ })
+ .optional(),
+});
+
+const StreamProxyConfig = z.object({
+ enabled: z.boolean().optional(),
+ id: z.enum(constants.PROXY_SERVICES).optional(),
+ url: z.string().optional(),
+ credentials: z.string().min(1).optional(),
+ publicIp: z.string().ip().optional(),
+ proxiedAddons: z.array(z.string().min(1)).optional(),
+ proxiedServices: z.array(z.string().min(1)).optional(),
+});
+
+export type StreamProxyConfig = z.infer;
+
+const ResultLimitOptions = z.object({
+ global: z.number().min(1).optional(),
+ service: z.number().min(1).optional(),
+ addon: z.number().min(1).optional(),
+ resolution: z.number().min(1).optional(),
+ quality: z.number().min(1).optional(),
+ streamType: z.number().min(1).optional(),
+ indexer: z.number().min(1).optional(),
+ releaseGroup: z.number().min(1).optional(),
+});
+
+// const SizeFilter = z.object({
+// min: z.number().min(1).optional(),
+// max: z.number().min(1).optional(),
+// });
+const SizeFilter = z.object({
+ movies: z
+ .tuple([z.number().min(0), z.number().min(0)])
+ // .object({
+ // min: z.number().min(1).optional(),
+ // max: z.number().min(1).optional(),
+ // })
+ .optional(),
+ series: z
+ .tuple([z.number().min(0), z.number().min(0)])
+ // .object({
+ // min: z.number().min(1).optional(),
+ // max: z.number().min(1).optional(),
+ // })
+ .optional(),
+});
+
+const SizeFilterOptions = z.object({
+ global: SizeFilter,
+ resolution: z.record(Resolutions, SizeFilter).optional(),
+});
+
+const ServiceSchema = z.object({
+ id: ServiceIds,
+ enabled: z.boolean().optional(),
+ credentials: z.record(z.string().min(1), z.string().min(1)),
+});
+
+export type Service = z.infer;
+
+const ServiceList = z.array(ServiceSchema);
+
+const ResourceSchema = z.enum(constants.RESOURCES);
+
+export type Resource = z.infer;
+
+const ResourceList = z.array(ResourceSchema);
+
+const AddonSchema = z.object({
+ id: z.string().min(1).optional(),
+ manifestUrl: z.string().url(),
+ enabled: z.boolean(),
+ resources: ResourceList.optional(),
+ name: z.string().min(1),
+ identifyingName: z.string().min(1),
+ timeout: z.number().min(1),
+ library: z.boolean().optional(),
+ streamPassthrough: z.boolean().optional(),
+ fromPresetId: z.string().min(1).optional(),
+ headers: z.record(z.string().min(1), z.string().min(1)).optional(),
+ ip: z.string().ip().optional(),
+});
+
+// preset objects are transformed into addons by a preset transformer.
+const PresetSchema = z.object({
+ id: z.string().min(1),
+ enabled: z.boolean(),
+ options: z.record(z.string().min(1), z.any()),
+});
+
+export type PresetObject = z.infer;
+
+const AddonList = z.array(AddonSchema);
+const PresetList = z.array(PresetSchema);
+
+export type Addon = z.infer;
+export type Preset = z.infer;
+
+const DeduplicatorKey = z.enum(constants.DEDUPLICATOR_KEYS);
+
+// deduplicator options.
+// can choose what keys to use for identifying duplicates.
+// can choose how duplicates are removed specifically.
+// we can either
+// - keep only 1 result from the highest priority service from the highest priority addon (single_result)
+// - keep 1 result for each enabled service from the higest priority addon (per_service)
+// - keep 1 result from the highest priority service from each enabled addon (per_addon)
+const DeduplicatorMode = z.enum([
+ 'single_result',
+ 'per_service',
+ 'per_addon',
+ 'disabled',
+]);
+
+const DeduplicatorOptions = z.object({
+ enabled: z.boolean().optional(),
+ keys: z.array(DeduplicatorKey).optional(),
+ cached: DeduplicatorMode.optional(),
+ uncached: DeduplicatorMode.optional(),
+ p2p: DeduplicatorMode.optional(),
+ http: DeduplicatorMode.optional(),
+ live: DeduplicatorMode.optional(),
+ youtube: DeduplicatorMode.optional(),
+ external: DeduplicatorMode.optional(),
+});
+
+const OptionDefinition = z.object({
+ id: z.string().min(1),
+ name: z.string().min(1),
+ description: z.string().min(1),
+ emptyIsUndefined: z.boolean().optional(),
+ type: z.enum([
+ 'string',
+ 'password',
+ 'number',
+ 'boolean',
+ 'select',
+ 'multi-select',
+ 'url',
+ ]),
+ required: z.boolean().optional(),
+ default: z.any().optional(),
+ // sensitive: z.boolean().optional(),
+ forced: z.any().optional(),
+ options: z
+ .array(
+ z.object({
+ value: z.any(),
+ label: z.string().min(1),
+ })
+ )
+ .optional(),
+ constraints: z
+ .object({
+ min: z.number().min(1).optional(), // for string inputs, consider this the minimum length.
+ max: z.number().min(1).optional(), // and for number inputs, consider this the minimum and maximum value.
+ })
+ .optional(),
+});
+
+export type Option = z.infer;
+
+const NameableRegex = z.object({
+ name: z.string().min(0),
+ pattern: z.string().min(1),
+});
+
+const Group = z.object({
+ addons: z.array(z.string().min(1)).min(1),
+ condition: z.string().min(1).max(200),
+});
+
+export type Group = z.infer;
+
+// Resolution, Quality, Encode, Visual Tag, Audio Tag, Stream Type, Keyword, Regex, Cached, Uncached, Size
+
+const CatalogModification = z.object({
+ id: z.string().min(1), // an id that maps to an actual catalog ID
+ type: z.string().min(1), // the type of catalog modification
+ name: z.string().min(1).optional(), // override the name of the catalog
+ shuffle: z.boolean().optional(), // shuffle the catalog
+ onlyOnDiscover: z.boolean().optional(), // only show the catalog on the discover page
+ enabled: z.boolean().optional(), // enable or disable the catalog
+ rpdb: z.boolean().optional(), // use rpdb for posters if supported
+ hideable: z.boolean().optional(), // hide the catalog from the home page
+ addonName: z.string().min(1).optional(), // the name of the addon that provides the catalog
+});
+
+export const UserDataSchema = z.object({
+ uuid: z.string().uuid().optional(),
+ encryptedPassword: z.string().min(1).optional(),
+ trusted: z.boolean().optional(),
+ addonPassword: z.string().min(1).optional(),
+ ip: z.string().ip().optional(),
+ addonName: z.string().min(1).optional(),
+ addonLogo: z.string().url().optional(),
+ addonBackground: z.string().url().optional(),
+ addonDescription: z.string().min(1).optional(),
+ excludedResolutions: z.array(Resolutions).optional(),
+ includedResolutions: z.array(Resolutions).optional(),
+ requiredResolutions: z.array(Resolutions).optional(),
+ preferredResolutions: z.array(Resolutions).optional(),
+ excludedQualities: z.array(Qualities).optional(),
+ includedQualities: z.array(Qualities).optional(),
+ requiredQualities: z.array(Qualities).optional(),
+ preferredQualities: z.array(Qualities).optional(),
+ excludedLanguages: z.array(Languages).optional(),
+ includedLanguages: z.array(Languages).optional(),
+ requiredLanguages: z.array(Languages).optional(),
+ preferredLanguages: z.array(Languages).optional(),
+ excludedVisualTags: z.array(VisualTags).optional(),
+ includedVisualTags: z.array(VisualTags).optional(),
+ requiredVisualTags: z.array(VisualTags).optional(),
+ preferredVisualTags: z.array(VisualTags).optional(),
+ excludedAudioTags: z.array(AudioTags).optional(),
+ includedAudioTags: z.array(AudioTags).optional(),
+ requiredAudioTags: z.array(AudioTags).optional(),
+ preferredAudioTags: z.array(AudioTags).optional(),
+ excludedAudioChannels: z.array(AudioChannels).optional(),
+ includedAudioChannels: z.array(AudioChannels).optional(),
+ requiredAudioChannels: z.array(AudioChannels).optional(),
+ preferredAudioChannels: z.array(AudioChannels).optional(),
+ excludedStreamTypes: z.array(StreamTypes).optional(),
+ includedStreamTypes: z.array(StreamTypes).optional(),
+ requiredStreamTypes: z.array(StreamTypes).optional(),
+ preferredStreamTypes: z.array(StreamTypes).optional(),
+ excludedEncodes: z.array(Encodes).optional(),
+ includedEncodes: z.array(Encodes).optional(),
+ requiredEncodes: z.array(Encodes).optional(),
+ preferredEncodes: z.array(Encodes).optional(),
+ excludedRegexPatterns: z.array(z.string().min(1)).optional(),
+ includedRegexPatterns: z.array(z.string().min(1)).optional(),
+ requiredRegexPatterns: z.array(z.string().min(1)).optional(),
+ preferredRegexPatterns: z.array(NameableRegex).optional(),
+ requiredKeywords: z.array(z.string().min(1)).optional(),
+ includedKeywords: z.array(z.string().min(1)).optional(),
+ excludedKeywords: z.array(z.string().min(1)).optional(),
+ preferredKeywords: z.array(z.string().min(1)).optional(),
+
+ randomiseResults: z.boolean().optional(),
+ enhanceResults: z.boolean().optional(),
+ enhancePosters: z.boolean().optional(),
+
+ excludeSeederRange: z
+ .tuple([z.number().min(0), z.number().min(0)])
+ .optional(),
+ includeSeederRange: z
+ .tuple([z.number().min(0), z.number().min(0)])
+ .optional(),
+ requiredSeederRange: z
+ .tuple([z.number().min(0), z.number().min(0)])
+ .optional(),
+ seederRangeTypes: z.array(z.enum(['p2p', 'cached', 'uncached'])).optional(),
+ excludeCached: z.boolean().optional(),
+ excludeCachedFromAddons: z.array(z.string().min(1)).optional(),
+ excludeCachedFromServices: z.array(z.string().min(1)).optional(),
+ excludeCachedFromStreamTypes: z.array(StreamTypes).optional(),
+ excludeCachedMode: z.enum(['or', 'and']).optional(),
+ excludeUncached: z.boolean().optional(),
+ excludeUncachedFromAddons: z.array(z.string().min(1)).optional(),
+ excludeUncachedFromServices: z.array(z.string().min(1)).optional(),
+ excludeUncachedFromStreamTypes: z.array(StreamTypes).optional(),
+ excludeUncachedMode: z.enum(['or', 'and']).optional(),
+ groups: z
+ .array(
+ z.object({
+ addons: z.array(z.string().min(1)),
+ condition: z.string().min(1).max(200),
+ })
+ )
+ .optional(),
+ sortCriteria: z.object({
+ // global must be defined.
+ global: z.array(SortCriterion),
+ // results must be from either a movie or series search, so we can safely apply different sort criteria.
+ movies: z.array(SortCriterion).optional(),
+ series: z.array(SortCriterion).optional(),
+ // cached and uncached results are a sort criteria themselves, so this can only be applied when cache is high enough in the global
+ // sort criteria, and we would have to split the results into two (cached and uncached) lists, and then apply both sort criteria below
+ // and then merge the results.
+ cached: z.array(SortCriterion).optional(),
+ uncached: z.array(SortCriterion).optional(),
+ cachedMovies: z.array(SortCriterion).optional(),
+ uncachedMovies: z.array(SortCriterion).optional(),
+ cachedSeries: z.array(SortCriterion).optional(),
+ uncachedSeries: z.array(SortCriterion).optional(),
+ }),
+ rpdbApiKey: z.string().optional(),
+ formatter: Formatter,
+ proxy: StreamProxyConfig.optional(),
+ resultLimits: ResultLimitOptions.optional(),
+ size: SizeFilterOptions.optional(),
+ hideErrors: z.boolean().optional(),
+ hideErrorsForResources: z.array(ResourceSchema).optional(),
+ tmdbAccessToken: z.string().optional(),
+ titleMatching: z
+ .object({
+ mode: z.enum(['exact', 'contains']).optional(),
+ enabled: z.boolean().optional(),
+ requestTypes: z.array(z.string()).optional(),
+ addons: z.array(z.string()).optional(),
+ })
+ .optional(),
+ seasonEpisodeMatching: z
+ .object({
+ enabled: z.boolean().optional(),
+ requestTypes: z.array(z.string()).optional(),
+ addons: z.array(z.string()).optional(),
+ })
+ .optional(),
+ deduplicator: DeduplicatorOptions.optional(),
+ precacheNextEpisode: z.boolean().optional(),
+ services: ServiceList.optional(),
+ presets: PresetList,
+ catalogModifications: z.array(CatalogModification).optional(),
+});
+
+export type UserData = z.infer;
+
+export const TABLES = {
+ USERS: `
+ uuid TEXT PRIMARY KEY,
+ password_hash TEXT NOT NULL,
+ config TEXT NOT NULL,
+ config_salt TEXT NOT NULL,
+ created_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP),
+ updated_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP),
+ accessed_at TIMESTAMP DEFAULT (CURRENT_TIMESTAMP)
+ `,
+};
+
+const strictManifestResourceSchema = z.object({
+ name: z.enum(constants.RESOURCES),
+ types: z.array(z.string()),
+ idPrefixes: z.array(z.string().min(1)).optional(),
+});
+
+export type StrictManifestResource = z.infer<
+ typeof strictManifestResourceSchema
+>;
+
+const ManifestResourceSchema = z.union([
+ z.string(),
+ strictManifestResourceSchema,
+]);
+
+const ManifestExtraSchema = z.object({
+ name: z.string().min(1),
+ isRequired: z.boolean().optional(),
+ options: z.array(z.string()).optional(),
+ optionsLimit: z.number().min(1).optional(),
+});
+const ManifestCatalogSchema = z.object({
+ type: z.string(),
+ id: z.string().min(1),
+ name: z.string().min(1),
+ extra: z.array(ManifestExtraSchema).optional(),
+});
+
+const AddonCatalogDefinitionSchema = z.object({
+ type: z.string(),
+ id: z.string().min(1),
+ name: z.string().min(1),
+});
+
+export const ManifestSchema = z.object({
+ id: z.string().min(1),
+ name: z.string().min(1),
+ description: z.string().min(1),
+ version: z.string().min(1),
+ types: z.array(z.string()),
+ idPrefixes: z.array(z.string().min(1)).optional(),
+ resources: z.array(ManifestResourceSchema),
+ catalogs: z.array(ManifestCatalogSchema),
+ addonCatalogs: z.array(AddonCatalogDefinitionSchema).optional(),
+ background: z.string().min(1).optional(),
+ logo: z.string().optional(),
+ contactEmail: z.string().min(1).optional(),
+ behaviorHints: z
+ .object({
+ adult: z.boolean().optional(),
+ p2p: z.boolean().optional(),
+ configurable: z.boolean().optional(),
+ configurationRequired: z.boolean().optional(),
+ })
+ .optional(),
+ // not part of the manifest scheme, but needed for stremio-addons.net
+ stremioAddonsConfig: z
+ .object({
+ issuer: z.string().min(1),
+ signature: z.string().min(1),
+ })
+ .optional(),
+});
+
+export type Manifest = z.infer;
+
+export const SubtitleSchema = z
+ .object({
+ id: z.string().min(1),
+ url: z.string().url(),
+ lang: z.string().min(1),
+ })
+ .passthrough();
+
+export const SubtitleResponseSchema = z.object({
+ subtitles: z.array(SubtitleSchema),
+});
+export type SubtitleResponse = z.infer;
+export type Subtitle = z.infer;
+
+export const StreamSchema = z
+ .object({
+ url: z.string().url().optional(),
+ ytId: z.string().min(1).optional(),
+ infoHash: z.string().min(1).or(z.null()).optional(),
+ fileIdx: z.number().or(z.null()).optional(),
+ externalUrl: z.string().min(1).optional(),
+ name: z.string().min(1).optional(),
+ title: z.string().min(1).optional(),
+ description: z.string().min(1).optional(),
+ subtitles: z.array(SubtitleSchema).optional(),
+ sources: z.array(z.string().min(1)).optional(),
+ behaviorHints: z
+ .object({
+ countryWhitelist: z.array(z.string().length(3)).optional(),
+ notWebReady: z.boolean().optional(),
+ bingeGroup: z.string().min(1).optional(),
+ proxyHeaders: z
+ .object({
+ request: z.record(z.string().min(1), z.string().min(1)).optional(),
+ response: z.record(z.string().min(1), z.string().min(1)).optional(),
+ })
+ .optional(),
+ videoHash: z.string().min(1).optional(),
+ videoSize: z.number().optional(),
+ filename: z.string().min(1).optional(),
+ })
+ .optional(),
+ })
+ .passthrough();
+
+export const StreamResponseSchema = z.object({
+ streams: z.array(StreamSchema),
+});
+
+export type StreamResponse = z.infer;
+
+export type Stream = z.infer;
+
+const TrailerSchema = z.object({
+ source: z.string().min(1),
+ type: z.enum(['Trailer']),
+});
+
+const MetaLinkSchema = z.object({
+ name: z.string().min(1),
+ category: z.string().min(1),
+ url: z.string().url().or(z.string().startsWith('stremio:///')),
+});
+
+const MetaVideoSchema = z.object({
+ id: z.string().min(1),
+ title: z.string().optional(),
+ released: z.string().datetime().optional(),
+ thumbnail: z.string().url().or(z.null()).optional(),
+ streams: z.array(StreamSchema).optional(),
+ available: z.boolean().optional(),
+ episode: z.number().optional(),
+ season: z.number().optional(),
+ trailers: z.array(TrailerSchema).optional(),
+ overview: z.string().optional(),
+});
+
+export const MetaPreviewSchema = z.object({
+ id: z.string().min(1),
+ type: z.string().min(1),
+ name: z.string().optional(),
+ poster: z.string().optional(),
+ posterShape: z.enum(['square', 'poster', 'landscape', 'regular']).optional(),
+ // discover sidebar
+ //@deprecated use links instead
+ genres: z.array(z.string()).optional(),
+ imdbRating: z.string().or(z.null()).or(z.number()).optional(),
+ releaseInfo: z.string().or(z.number()).or(z.null()).optional(),
+ //@deprecated
+ director: z.array(z.string()).or(z.null()).optional(),
+ //@deprecated
+ cast: z.array(z.string()).or(z.null()).optional(),
+ // background: z.string().min(1).optional(),
+ // logo: z.string().min(1).optional(),
+ description: z.string().or(z.null()).optional(),
+ trailers: z.array(TrailerSchema).optional(),
+ links: z.array(MetaLinkSchema).optional(),
+ // released: z.string().datetime().optional(),
+});
+
+export const MetaSchema = MetaPreviewSchema.extend({
+ poster: z.string().min(1).optional(),
+ background: z.string().min(1).optional(),
+ logo: z.string().optional(),
+ videos: z.array(MetaVideoSchema).optional(),
+ runtime: z.string().optional(),
+ language: z.string().min(1).optional(),
+ country: z.string().optional(),
+ awards: z.string().min(1).optional(),
+ website: z.string().url().optional(),
+ behaviorHints: z
+ .object({
+ defaultVideoId: z.string().or(z.null()).optional(),
+ })
+ .optional(),
+});
+
+export const MetaResponseSchema = z.object({
+ meta: MetaSchema,
+});
+export const CatalogResponseSchema = z.object({
+ metas: z.array(MetaPreviewSchema),
+});
+export type MetaResponse = z.infer;
+export type CatalogResponse = z.infer;
+export type Meta = z.infer;
+export type MetaPreview = z.infer;
+
+export const AddonCatalogSchema = z.object({
+ transportName: z.literal('http'),
+ transportUrl: z.string().url(),
+ manifest: ManifestSchema,
+});
+export const AddonCatalogResponseSchema = z.object({
+ addons: z.array(AddonCatalogSchema),
+});
+export type AddonCatalogResponse = z.infer;
+export type AddonCatalog = z.infer;
+
+const ParsedFileSchema = z.object({
+ releaseGroup: z.string().optional(),
+ resolution: z.string().optional(),
+ quality: z.string().optional(),
+ encode: z.string().optional(),
+ audioChannels: z.array(z.string()),
+ visualTags: z.array(z.string()),
+ audioTags: z.array(z.string()),
+ languages: z.array(z.string()),
+ title: z.string().optional(),
+ year: z.string().optional(),
+ season: z.number().optional(),
+ seasons: z.array(z.number()).optional(),
+ episode: z.number().optional(),
+ seasonEpisode: z.array(z.string()).optional(),
+});
+
+export type ParsedFile = z.infer;
+
+export const ParsedStreamSchema = z.object({
+ proxied: z.boolean().optional(),
+ addon: AddonSchema,
+ parsedFile: ParsedFileSchema.optional(),
+ message: z.string().max(1000).optional(),
+ regexMatched: z
+ .object({
+ name: z.string().min(1).optional(),
+ pattern: z.string().min(1).optional(),
+ index: z.number(),
+ })
+ .optional(),
+ keywordMatched: z.boolean().optional(),
+ size: z.number().optional(),
+ folderSize: z.number().optional(),
+ type: StreamTypes,
+ indexer: z.string().optional(),
+ age: z.string().optional(),
+ torrent: z
+ .object({
+ infoHash: z.string().min(1).or(z.null()).optional(),
+ fileIdx: z.number().or(z.null()).optional(),
+ seeders: z.number().optional(),
+ sources: z.array(z.string().min(1)).optional(), // array of tracker urls and DHT nodes
+ })
+ .optional(),
+ countryWhitelist: z.array(z.string().length(3)).optional(),
+ notWebReady: z.boolean().optional(),
+ bingeGroup: z.string().min(1).optional(),
+ requestHeaders: z.record(z.string().min(1), z.string().min(1)).optional(),
+ responseHeaders: z.record(z.string().min(1), z.string().min(1)).optional(),
+ videoHash: z.string().min(1).optional(),
+ subtitles: z.array(SubtitleSchema).optional(),
+ filename: z.string().optional(),
+ folderName: z.string().optional(),
+ service: z
+ .object({
+ id: z.enum(constants.SERVICES),
+ cached: z.boolean(),
+ })
+ .optional(),
+ duration: z.number().optional(),
+ library: z.boolean().optional(),
+ url: z.string().url().optional(),
+ ytId: z.string().min(1).optional(),
+ externalUrl: z.string().min(1).optional(),
+ error: z
+ .object({
+ title: z.string().min(1),
+ description: z.string().min(1),
+ })
+ .optional(),
+ originalName: z.string().optional(),
+ originalDescription: z.string().optional(),
+});
+
+export type ParsedStream = z.infer;
+
+export const AIOStream = StreamSchema.extend({
+ streamData: z.object({
+ error: z
+ .object({
+ title: z.string().min(1),
+ description: z.string().min(1),
+ })
+ .optional(),
+ proxied: z.boolean().optional(),
+ addon: z.string().optional(),
+ filename: z.string().optional(),
+ folderName: z.string().optional(),
+ service: z
+ .object({
+ id: z.enum(constants.SERVICES),
+ cached: z.boolean(),
+ })
+ .optional(),
+ parsedFile: ParsedFileSchema.optional(),
+ message: z.string().max(1000).optional(),
+ regexMatched: z
+ .object({
+ name: z.string().min(1).optional(),
+ pattern: z.string().min(1).optional(),
+ index: z.number(),
+ })
+ .optional(),
+ keywordMatched: z.boolean().optional(),
+ size: z.number().optional(),
+ folderSize: z.number().optional(),
+ type: StreamTypes.optional(),
+ indexer: z.string().optional(),
+ age: z.string().optional(),
+ torrent: z
+ .object({
+ infoHash: z.string().min(1).or(z.null()).optional(),
+ fileIdx: z.number().or(z.null()).optional(),
+ seeders: z.number().optional(),
+ sources: z.array(z.string().min(1)).optional(), // array of tracker urls and DHT nodes
+ })
+ .optional(),
+ duration: z.number().optional(),
+ library: z.boolean().optional(),
+ }),
+});
+
+export type AIOStream = z.infer;
+
+const AIOStreamResponseSchema = z.object({
+ streams: z.array(AIOStream),
+});
+export type AIOStreamResponse = z.infer;
+
+const PresetMetadataSchema = z.object({
+ ID: z.string(),
+ NAME: z.string(),
+ DISABLED: z
+ .object({
+ reason: z.string(),
+ disabled: z.boolean(),
+ })
+ .optional(),
+ LOGO: z.string(),
+ DESCRIPTION: z.string(),
+ URL: z.string(),
+ TIMEOUT: z.number(),
+ USER_AGENT: z.string(),
+ SUPPORTED_SERVICES: z.array(z.string()),
+ OPTIONS: z.array(OptionDefinition),
+ SUPPORTED_STREAM_TYPES: z.array(StreamTypes),
+ SUPPORTED_RESOURCES: z.array(ResourceSchema),
+});
+
+const StatusResponseSchema = z.object({
+ version: z.string(),
+ tag: z.string(),
+ commit: z.string(),
+ buildTime: z.string(),
+ commitTime: z.string(),
+ users: z.number(),
+ settings: z.object({
+ baseUrl: z.string().url().optional(),
+ addonName: z.string(),
+ customHtml: z.string().optional(),
+ protected: z.boolean(),
+ regexFilterAccess: z.enum(['none', 'trusted', 'all']),
+ tmdbApiAvailable: z.boolean(),
+ forced: z.object({
+ proxy: z.object({
+ enabled: z.boolean().or(z.null()),
+ id: z.string().or(z.null()),
+ url: z.string().or(z.null()),
+ publicIp: z.string().or(z.null()),
+ credentials: z.string().or(z.null()),
+ disableProxiedAddons: z.boolean(),
+ proxiedServices: z.array(z.string()).or(z.null()),
+ }),
+ }),
+ defaults: z.object({
+ proxy: z.object({
+ enabled: z.boolean().or(z.null()),
+ id: z.string().or(z.null()),
+ url: z.string().or(z.null()),
+ publicIp: z.string().or(z.null()),
+ credentials: z.string().or(z.null()),
+ proxiedServices: z.array(z.string()).or(z.null()),
+ }),
+ timeout: z.number().or(z.null()),
+ }),
+ presets: z.array(PresetMetadataSchema),
+ services: z.record(
+ z.enum(constants.SERVICES),
+ z.object({
+ id: z.enum(constants.SERVICES),
+ name: z.string(),
+ shortName: z.string(),
+ knownNames: z.array(z.string()),
+ signUpText: z.string(),
+ credentials: z.array(OptionDefinition),
+ })
+ ),
+ }),
+});
+
+export type StatusResponse = z.infer;
+export type PresetMetadata = z.infer;
diff --git a/packages/core/src/db/users.ts b/packages/core/src/db/users.ts
new file mode 100644
index 00000000..b701683e
--- /dev/null
+++ b/packages/core/src/db/users.ts
@@ -0,0 +1,383 @@
+// import { UserDataSchema, UserData, DB } from '../db';
+import { UserDataSchema, UserData } from './schemas';
+import { TransactionQueue } from './queue';
+import { DB } from './db';
+import {
+ decryptString,
+ deriveKey,
+ encryptString,
+ generateUUID,
+ getTextHash,
+ maskSensitiveInfo,
+ createLogger,
+ constants,
+ Env,
+ verifyHash,
+ validateConfig,
+ formatZodError,
+} from '../utils';
+
+const APIError = constants.APIError;
+const logger = createLogger('users');
+const db = DB.getInstance();
+const txQueue = TransactionQueue.getInstance();
+
+export class UserRepository {
+ static async createUser(
+ config: UserData,
+ password: string
+ ): Promise<{ uuid: string; encryptedPassword: string }> {
+ return txQueue.enqueue(async () => {
+ if (password.length < 8) {
+ return Promise.reject(
+ new APIError(constants.ErrorCode.USER_NEW_PASSWORD_TOO_SHORT)
+ );
+ }
+
+ // require at least one uppercase, one lowercase, one number, and one special character
+ // [@$!%*?&\-\._#~^()+=<>,;:'"`{}[\]|\\]
+ if (
+ !/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&\-\._#~^()+=<>,;:'"`{}[\]|\\])[A-Za-z\d@$!%*?&\-\._#~^()+=<>,;:'"`{}[\]|\\]{8,}$/.test(
+ password
+ )
+ ) {
+ return Promise.reject(
+ new APIError(constants.ErrorCode.USER_NEW_PASSWORD_TOO_SIMPLE)
+ );
+ }
+
+ let validatedConfig: UserData;
+ try {
+ // don't skip errors, but don't decrypt credentials
+ // as we need to store the encrypted version
+ validatedConfig = await validateConfig(config, false, false);
+ } catch (error: any) {
+ logger.error(`Invalid config for new user: ${error.message}`);
+ return Promise.reject(
+ new APIError(
+ constants.ErrorCode.USER_INVALID_CONFIG,
+ undefined,
+ error.message
+ )
+ );
+ }
+
+ const uuid = await this.generateUUID();
+
+ const { encryptedConfig, salt: configSalt } = await this.encryptConfig(
+ validatedConfig,
+ password
+ );
+ const hashedPassword = await getTextHash(password);
+
+ const { success, data } = encryptString(password);
+ if (success === false) {
+ return Promise.reject(constants.ErrorCode.USER_ERROR);
+ }
+
+ const encryptedPassword = data;
+ let tx;
+ let committed = false;
+ try {
+ tx = await db.begin();
+ await tx.execute(
+ 'INSERT INTO users (uuid, password_hash, config, config_salt) VALUES (?, ?, ?, ?)',
+ [uuid, hashedPassword, encryptedConfig, configSalt]
+ );
+ await tx.commit();
+ committed = true;
+ logger.info(`Created a new user with UUID: ${uuid}`);
+ return { uuid, encryptedPassword };
+ } catch (error) {
+ logger.error(
+ `Failed to create user: ${error instanceof Error ? error.message : String(error)}`
+ );
+ if (error instanceof APIError) {
+ throw error;
+ }
+ throw new APIError(constants.ErrorCode.INTERNAL_SERVER_ERROR);
+ } finally {
+ if (tx && !committed) {
+ await tx.rollback();
+ }
+ }
+ });
+ }
+
+ static async checkUserExists(uuid: string): Promise {
+ try {
+ const result = await db.query('SELECT uuid FROM users WHERE uuid = ?', [
+ uuid,
+ ]);
+ return result.length > 0;
+ } catch (error) {
+ logger.error(`Error checking user existence: ${error}`);
+ return Promise.reject(constants.ErrorCode.USER_ERROR);
+ }
+ }
+
+ // with stremio auth, we are given the encrypted password
+ // with api use, we are given the password
+ // GET /user should also return
+
+ static async getUser(
+ uuid: string,
+ password: string
+ ): Promise {
+ try {
+ const result = await db.query(
+ 'SELECT config, config_salt, password_hash FROM users WHERE uuid = ?',
+ [uuid]
+ );
+
+ if (!result.length || !result[0].config) {
+ return Promise.reject(new APIError(constants.ErrorCode.USER_NOT_FOUND));
+ }
+
+ await db.execute(
+ 'UPDATE users SET accessed_at = CURRENT_TIMESTAMP WHERE uuid = ?',
+ [uuid]
+ );
+
+ const isValid = await this.verifyUserPassword(
+ password,
+ result[0].password_hash
+ );
+ if (!isValid) {
+ return Promise.reject(
+ new APIError(constants.ErrorCode.USER_INVALID_PASSWORD)
+ );
+ }
+
+ const decryptedConfig = await this.decryptConfig(
+ result[0].config,
+ password,
+ result[0].config_salt
+ );
+
+ // try {
+ // // skip errors, and dont decrypt credentials either, as this would make
+ // // encryption pointless
+ // validatedConfig = await validateConfig(decryptedConfig, true, false);
+ // } catch (error: any) {
+ // return Promise.reject(
+ // new APIError(
+ // constants.ErrorCode.USER_INVALID_CONFIG,
+ // undefined,
+ // error.message
+ // )
+ // );
+ // }
+ // const {
+ // success,
+ // data: validatedConfig,
+ // error,
+ // } = UserDataSchema.safeParse(decryptedConfig);
+ // if (!success) {
+ // return Promise.reject(
+ // new APIError(
+ // constants.ErrorCode.USER_INVALID_CONFIG,
+ // undefined,
+ // formatZodError(error)
+ // )
+ // );
+ // }
+ decryptedConfig.trusted =
+ Env.TRUSTED_UUIDS?.split(',').some((u) => new RegExp(u).test(uuid)) ??
+ false;
+ logger.info(`Retrieved configuration for user ${uuid}`);
+ return decryptedConfig;
+ } catch (error) {
+ logger.error(
+ `Error retrieving user ${uuid}: ${error instanceof Error ? error.message : String(error)}`
+ );
+ return Promise.reject(
+ new APIError(constants.ErrorCode.INTERNAL_SERVER_ERROR)
+ );
+ }
+ }
+
+ static async updateUser(
+ uuid: string,
+ password: string,
+ config: UserData
+ ): Promise {
+ return txQueue.enqueue(async () => {
+ let tx;
+ let committed = false;
+ try {
+ tx = await db.begin();
+ const currentUser = await tx.execute(
+ 'SELECT config_salt, password_hash FROM users WHERE uuid = ?',
+ [uuid]
+ );
+
+ if (!currentUser.rows.length) {
+ throw new APIError(constants.ErrorCode.USER_NOT_FOUND);
+ }
+ let validatedConfig: UserData;
+ try {
+ validatedConfig = await validateConfig(config, false, false);
+ } catch (error: any) {
+ throw new APIError(
+ constants.ErrorCode.USER_INVALID_CONFIG,
+ undefined,
+ error.message
+ );
+ }
+ const storedHash = currentUser.rows[0].password_hash;
+ const isValid = await this.verifyUserPassword(password, storedHash);
+ if (!isValid) {
+ throw new APIError(constants.ErrorCode.USER_INVALID_PASSWORD);
+ }
+ const { encryptedConfig } = await this.encryptConfig(
+ validatedConfig,
+ password,
+ currentUser.rows[0].config_salt
+ );
+ await tx.execute(
+ 'UPDATE users SET config = ?, updated_at = CURRENT_TIMESTAMP WHERE uuid = ?',
+ [encryptedConfig, uuid]
+ );
+ await tx.commit();
+ committed = true;
+ logger.info(`Updated user ${uuid} with an updated configuration`);
+ } catch (error) {
+ logger.error(
+ `Failed to update user ${uuid}: ${error instanceof Error ? error.message : String(error)}`
+ );
+ if (error instanceof APIError) {
+ throw error;
+ }
+ throw new APIError(constants.ErrorCode.INTERNAL_SERVER_ERROR);
+ } finally {
+ if (tx && !committed) {
+ await tx.rollback();
+ }
+ }
+ });
+ }
+
+ static async getUserCount(): Promise {
+ try {
+ const result = await db.query('SELECT * FROM users');
+ return result.length;
+ } catch (error) {
+ logger.error(`Error getting user count: ${error}`);
+ return Promise.reject(new APIError(constants.ErrorCode.USER_ERROR));
+ }
+ }
+
+ static async deleteUser(uuid: string): Promise {
+ return txQueue.enqueue(async () => {
+ let tx;
+ let committed = false;
+ try {
+ tx = await db.begin();
+ const result = await tx.execute('DELETE FROM users WHERE uuid = ?', [
+ uuid,
+ ]);
+
+ if (result.rowCount === 0) {
+ throw new APIError(constants.ErrorCode.USER_NOT_FOUND);
+ }
+
+ await tx.commit();
+ committed = true;
+ logger.info(`Deleted user ${uuid}`);
+ } catch (error) {
+ logger.error(
+ `Failed to delete user ${uuid}: ${error instanceof Error ? error.message : String(error)}`
+ );
+ if (error instanceof APIError) {
+ throw error;
+ }
+ throw new APIError(constants.ErrorCode.INTERNAL_SERVER_ERROR);
+ } finally {
+ if (tx && !committed) {
+ await tx.rollback();
+ }
+ }
+ });
+ }
+
+ static async pruneUsers(maxDays: number = 30): Promise {
+ try {
+ const query =
+ db.getDialect() === 'postgres'
+ ? `DELETE FROM users WHERE accessed_at < NOW() - INTERVAL '${maxDays} days'`
+ : `DELETE FROM users WHERE accessed_at < datetime('now', '-' || ${maxDays} || ' days')`;
+
+ const result = await db.execute(query);
+ const deletedCount = result.changes || result.rowCount || 0;
+ logger.info(`Pruned ${deletedCount} users older than ${maxDays} days`);
+ return deletedCount;
+ } catch (error) {
+ logger.error('Failed to prune users:', error);
+ return Promise.reject(new APIError(constants.ErrorCode.USER_ERROR));
+ }
+ }
+
+ private static async verifyUserPassword(
+ password: string,
+ storedHash: string
+ ): Promise {
+ return verifyHash(password, storedHash);
+ }
+
+ private static async encryptConfig(
+ config: UserData,
+ password: string,
+ salt?: string
+ ): Promise<{
+ encryptedConfig: string;
+ salt: string;
+ }> {
+ const { key, salt: saltUsed } = await deriveKey(
+ `${password}:${Env.SECRET_KEY}`,
+ salt
+ );
+ const configString = JSON.stringify(config);
+ const { success, data, error } = encryptString(configString, key);
+
+ if (!success) {
+ return Promise.reject(new APIError(constants.ErrorCode.USER_ERROR));
+ }
+
+ return { encryptedConfig: data, salt: saltUsed };
+ }
+
+ private static async decryptConfig(
+ encryptedConfig: string,
+ password: string,
+ salt: string
+ ): Promise {
+ const { key } = await deriveKey(`${password}:${Env.SECRET_KEY}`, salt);
+ const {
+ success,
+ data: decryptedString,
+ error,
+ } = decryptString(encryptedConfig, key);
+
+ if (!success || !decryptedString) {
+ return Promise.reject(new APIError(constants.ErrorCode.USER_ERROR));
+ }
+
+ return JSON.parse(decryptedString);
+ }
+
+ private static async generateUUID(count: number = 1): Promise {
+ if (count > 10) {
+ return Promise.reject(new APIError(constants.ErrorCode.USER_ERROR));
+ }
+
+ const uuid = generateUUID();
+ const existingUser = await this.checkUserExists(uuid);
+
+ if (existingUser) {
+ return this.generateUUID(count + 1);
+ }
+
+ return uuid;
+ }
+}
diff --git a/packages/core/src/db/utils.ts b/packages/core/src/db/utils.ts
new file mode 100644
index 00000000..a239c630
--- /dev/null
+++ b/packages/core/src/db/utils.ts
@@ -0,0 +1,77 @@
+import { URL } from 'url';
+import { createLogger } from '../utils/logger';
+import path from 'path';
+
+type BaseConnectionURI = {
+ url: URL;
+ driverName: string;
+};
+
+type PostgresConnectionURI = BaseConnectionURI & {
+ dialect: 'postgres';
+};
+
+type SQLiteConnectionURI = BaseConnectionURI & {
+ filename: string;
+ dialect: 'sqlite';
+};
+
+export type ConnectionURI = PostgresConnectionURI | SQLiteConnectionURI;
+
+type DBDialect = 'postgres' | 'sqlite';
+
+type DSNModifier = (url: URL, query: URLSearchParams) => void;
+const logger = createLogger('database');
+
+function parseConnectionURI(uri: string): ConnectionURI {
+ const url = new URL(uri);
+ let driverName: string;
+ let dialect: DBDialect;
+
+ switch (url.protocol) {
+ case 'sqlite:': {
+ driverName = 'sqlite3';
+ dialect = 'sqlite';
+ let filename = url.pathname;
+ if (url.hostname && url.hostname !== '.') {
+ throw new Error("Invalid path, must start with '/' or './'");
+ }
+ if (!url.pathname) {
+ throw new Error('Invalid path, must be absolute');
+ }
+ if (url.hostname === '.') {
+ // resolve relative path using process.cwd()
+ filename = path.join(process.cwd(), url.pathname.replace(/^\//, ''));
+ }
+ return {
+ url,
+ driverName,
+ filename: filename,
+ dialect,
+ };
+ }
+ case 'postgres:': {
+ driverName = 'pg';
+ dialect = 'postgres';
+ return {
+ url,
+
+ driverName,
+ dialect,
+ };
+ }
+ default:
+ throw new Error('Unsupported scheme: ' + url.protocol);
+ }
+}
+
+function adaptQuery(query: string, dialect: DBDialect): string {
+ if (dialect === 'sqlite') {
+ return query;
+ }
+
+ let position = 1;
+ return query.replace(/\?/g, () => `$${position++}`);
+}
+
+export { parseConnectionURI, adaptQuery };
diff --git a/packages/core/src/formatters/Intl.d.ts b/packages/core/src/formatters/Intl.d.ts
new file mode 100644
index 00000000..817f2a33
--- /dev/null
+++ b/packages/core/src/formatters/Intl.d.ts
@@ -0,0 +1,12 @@
+// vs code...
+declare namespace Intl {
+ type Key =
+ | 'calendar'
+ | 'collation'
+ | 'currency'
+ | 'numberingSystem'
+ | 'timeZone'
+ | 'unit';
+
+ function supportedValuesOf(input: Key): string[];
+}
diff --git a/packages/core/src/formatters/base.ts b/packages/core/src/formatters/base.ts
new file mode 100644
index 00000000..878db782
--- /dev/null
+++ b/packages/core/src/formatters/base.ts
@@ -0,0 +1,593 @@
+import { ParsedStream } from '../db';
+// import { constants, Env, createLogger } from '../utils';
+import * as constants from '../utils/constants';
+import { createLogger } from '../utils/logger';
+import { formatBytes, formatDuration, languageToEmoji } from './utils';
+import { Env } from '../utils/env';
+
+const logger = createLogger('formatter');
+
+/**
+ *
+ * The custom formatter code in this file was adapted from https://github.com/diced/zipline/blob/trunk/src/lib/parser/index.ts
+ *
+ * The original code is licensed under the MIT License.
+ *
+ * MIT License
+ *
+ * Copyright (c) 2023 dicedtomato
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+export interface FormatterConfig {
+ name: string;
+ description: string;
+}
+
+export interface ParseValue {
+ config?: {
+ addonName: string | null;
+ };
+ stream?: {
+ filename: string | null;
+ folderName: string | null;
+ size: number | null;
+ folderSize: number | null;
+ library: boolean | null;
+ quality: string | null;
+ resolution: string | null;
+ languages: string[] | null;
+ languageEmojis: string[] | null;
+ wedontknowwhatakilometeris: string[] | null;
+ visualTags: string[] | null;
+ audioTags: string[] | null;
+ releaseGroup: string | null;
+ regexMatched: string | null;
+ encode: string | null;
+ audioChannels: string[] | null;
+ indexer: string | null;
+ year: string | null;
+ title: string | null;
+ season: number | null;
+ seasons: number[] | null;
+ episode: number | null;
+ seasonEpisode: string[] | null;
+ seeders: number | null;
+ age: string | null;
+ duration: number | null;
+ infoHash: string | null;
+ type: string | null;
+ message: string | null;
+ proxied: boolean | null;
+ };
+ service?: {
+ id: string | null;
+ shortName: string | null;
+ name: string | null;
+ cached: boolean | null;
+ };
+ addon?: {
+ name: string;
+ manifestUrl: string;
+ };
+ debug?: {
+ json: string | null;
+ jsonf: string | null;
+ };
+}
+
+export abstract class BaseFormatter {
+ protected config: FormatterConfig;
+ protected addonName: string;
+
+ constructor(config: FormatterConfig, addonName?: string) {
+ this.config = config;
+ this.addonName = addonName || Env.ADDON_NAME;
+ }
+
+ public format(stream: ParsedStream): { name: string; description: string } {
+ const parseValue = this.convertStreamToParseValue(stream);
+ return {
+ name: this.parseString(this.config.name, parseValue) || '',
+ description: this.parseString(this.config.description, parseValue) || '',
+ };
+ }
+
+ protected convertStreamToParseValue(stream: ParsedStream): ParseValue {
+ return {
+ config: {
+ addonName: this.addonName,
+ },
+ stream: {
+ filename: stream.filename || null,
+ folderName: stream.folderName || null,
+ size: stream.size || null,
+ folderSize: stream.folderSize || null,
+ library: stream.library !== undefined ? stream.library : null,
+ quality: stream.parsedFile?.quality || null,
+ resolution: stream.parsedFile?.resolution || null,
+ languages: stream.parsedFile?.languages || null,
+ languageEmojis: stream.parsedFile?.languages
+ ? stream.parsedFile.languages
+ .map((lang) => languageToEmoji(lang) || lang)
+ .filter((value, index, self) => self.indexOf(value) === index)
+ : null,
+ wedontknowwhatakilometeris: stream.parsedFile?.languages
+ ? stream.parsedFile.languages
+ .map((lang) => languageToEmoji(lang) || lang)
+ .map((emoji) => emoji.replace('🇬🇧', '🇺🇸🦅'))
+ .filter((value, index, self) => self.indexOf(value) === index)
+ : null,
+ visualTags: stream.parsedFile?.visualTags || null,
+ audioTags: stream.parsedFile?.audioTags || null,
+ releaseGroup: stream.parsedFile?.releaseGroup || null,
+ regexMatched: stream.regexMatched?.name || null,
+ encode: stream.parsedFile?.encode || null,
+ audioChannels: stream.parsedFile?.audioChannels || null,
+ indexer: stream.indexer || null,
+ seeders: stream.torrent?.seeders ?? null,
+ year: stream.parsedFile?.year || null,
+ type: stream.type || null,
+ title: stream.parsedFile?.title || null,
+ season: stream.parsedFile?.season || null,
+ seasons: stream.parsedFile?.seasons || null,
+ episode: stream.parsedFile?.episode || null,
+ seasonEpisode: stream.parsedFile?.seasonEpisode || null,
+ duration: stream.duration || null,
+ infoHash: stream.torrent?.infoHash || null,
+ age: stream.age || null,
+ message: stream.message || null,
+ proxied: stream.proxied !== undefined ? stream.proxied : null,
+ },
+ addon: {
+ name: stream.addon.name,
+ manifestUrl: stream.addon.manifestUrl,
+ },
+ service: {
+ id: stream.service?.id || null,
+ shortName: stream.service?.id
+ ? Object.values(constants.SERVICE_DETAILS).find(
+ (service) => service.id === stream.service?.id
+ )?.shortName || null
+ : null,
+ name: stream.service?.id
+ ? Object.values(constants.SERVICE_DETAILS).find(
+ (service) => service.id === stream.service?.id
+ )?.name || null
+ : null,
+ cached:
+ stream.service?.cached !== undefined ? stream.service?.cached : null,
+ },
+ };
+ }
+
+ protected parseString(str: string, value: ParseValue): string | null {
+ if (!str) return null;
+
+ const replacer = (key: string, value: unknown) => {
+ return value;
+ };
+
+ const data = {
+ stream: value.stream,
+ service: value.service,
+ addon: value.addon,
+ config: value.config,
+ };
+
+ value.debug = {
+ json: JSON.stringify(data, replacer),
+ jsonf: JSON.stringify(data, replacer, 2),
+ };
+
+ const re =
+ /\{(?stream|service|addon|config|debug)\.(?\w+)(::(?(\w+(\([^)]*\))?|<|<=|=|>=|>|\^|\$|~|\/)+))?((::(?\S+?))|(?\[(?".*?")\|\|(?".*?")\]))?\}/gi;
+ let matches: RegExpExecArray | null;
+
+ while ((matches = re.exec(str))) {
+ if (!matches.groups) continue;
+
+ const index = matches.index as number;
+
+ const getV = value[matches.groups.type as keyof ParseValue];
+
+ if (!getV) {
+ str = this.replaceCharsFromString(
+ str,
+ '{unknown_type}',
+ index,
+ re.lastIndex
+ );
+ re.lastIndex = index;
+ continue;
+ }
+
+ const v =
+ getV[
+ matches.groups.prop as
+ | keyof ParseValue['stream']
+ | keyof ParseValue['service']
+ | keyof ParseValue['addon']
+ ];
+
+ if (v === undefined) {
+ str = this.replaceCharsFromString(
+ str,
+ '{unknown_value}',
+ index,
+ re.lastIndex
+ );
+ re.lastIndex = index;
+ continue;
+ }
+
+ if (matches.groups.mod) {
+ str = this.replaceCharsFromString(
+ str,
+ this.modifier(
+ matches.groups.mod,
+ v,
+ matches.groups.mod_tzlocale ?? undefined,
+ matches.groups.mod_check_true ?? undefined,
+ matches.groups.mod_check_false ?? undefined,
+ value
+ ),
+ index,
+ re.lastIndex
+ );
+ re.lastIndex = index;
+ continue;
+ }
+
+ str = this.replaceCharsFromString(str, v, index, re.lastIndex);
+ re.lastIndex = index;
+ }
+
+ return str
+ .replace(/\\n/g, '\n')
+ .split('\n')
+ .filter(
+ (line) => line.trim() !== '' && !line.includes('{tools.removeLine}')
+ )
+ .join('\n')
+ .replace(/\{tools.newLine\}/g, '\n');
+ }
+
+ protected modifier(
+ mod: string,
+ value: unknown,
+ tzlocale?: string,
+ check_true?: string,
+ check_false?: string,
+ _value?: ParseValue
+ ): string {
+ mod = mod.toLowerCase();
+ check_true = check_true?.slice(1, -1);
+ check_false = check_false?.slice(1, -1);
+
+ if (Array.isArray(value)) {
+ switch (true) {
+ case mod === 'join':
+ return value.join(', ');
+ case mod.startsWith('join(') && mod.endsWith(')'): {
+ // Extract the separator from join(separator)
+ // e.g. join(' - ')
+ const separator = mod
+ .substring(5, mod.length - 1)
+ .replace(/^['"]|['"]$/g, '');
+ return value.join(separator);
+ }
+ case mod == 'length':
+ return value.length.toString();
+ case mod == 'first':
+ return value.length > 0 ? String(value[0]) : '';
+ case mod == 'last':
+ return value.length > 0 ? String(value[value.length - 1]) : '';
+ case mod == 'random':
+ return value.length > 0
+ ? String(value[Math.floor(Math.random() * value.length)])
+ : '';
+ case mod == 'sort':
+ return [...value].sort().join(', ');
+ case mod == 'reverse':
+ return [...value].reverse().join(', ');
+ case mod.startsWith('~'): {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_array_modifier(${mod})}`;
+
+ const check = mod.replace('~', '').replace('_', ' ');
+
+ if (_value) {
+ return value.some((item) => item.toLowerCase().includes(check))
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return value.some((item) => item.toLowerCase().includes(check))
+ ? check_true
+ : check_false;
+ }
+ case mod == 'exists': {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_array_modifier(${mod})}`;
+
+ if (_value) {
+ return value.length > 0
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return value.length > 0 ? check_true : check_false;
+ }
+ default:
+ return `{unknown_array_modifier(${mod})}`;
+ }
+ } else if (typeof value === 'string') {
+ switch (true) {
+ case mod == 'upper':
+ return value.toUpperCase();
+ case mod == 'lower':
+ return value.toLowerCase();
+ case mod == 'title':
+ return value.charAt(0).toUpperCase() + value.slice(1);
+ case mod == 'length':
+ return value.length.toString();
+ case mod == 'reverse':
+ return value.split('').reverse().join('');
+ case mod == 'base64':
+ return btoa(value);
+ case mod == 'string':
+ return value;
+ case mod == 'exists': {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_str_modifier(${mod})}`;
+
+ if (_value) {
+ return value != 'null' && value
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return value != 'null' && value ? check_true : check_false;
+ }
+ case mod.startsWith('='): {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_str_modifier(${mod})}`;
+
+ const check = mod.replace('=', '');
+
+ if (!check) return `{unknown_str_modifier(${mod})}`;
+
+ if (_value) {
+ return value.toLowerCase() == check
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return value.toLowerCase() == check ? check_true : check_false;
+ }
+ case mod.startsWith('$'): {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_str_modifier(${mod})}`;
+
+ const check = mod.replace('$', '');
+
+ if (!check) return `{unknown_str_modifier(${mod})}`;
+
+ if (_value) {
+ return value.toLowerCase().startsWith(check)
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return value.toLowerCase().startsWith(check)
+ ? check_true
+ : check_false;
+ }
+ case mod.startsWith('^'): {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_str_modifier(${mod})}`;
+
+ const check = mod.replace('^', '');
+
+ if (!check) return `{unknown_str_modifier(${mod})}`;
+
+ if (_value) {
+ return value.toLowerCase().endsWith(check)
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return value.toLowerCase().endsWith(check) ? check_true : check_false;
+ }
+ case mod.startsWith('~'): {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_str_modifier(${mod})}`;
+
+ const check = mod.replace('~', '');
+
+ if (!check) return `{unknown_str_modifier(${mod})}`;
+
+ if (_value) {
+ return value.toLowerCase().includes(check)
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return value.toLowerCase().includes(check) ? check_true : check_false;
+ }
+ default:
+ return `{unknown_str_modifier(${mod})}`;
+ }
+ } else if (typeof value === 'number') {
+ switch (true) {
+ case mod == 'comma':
+ return value.toLocaleString();
+ case mod == 'hex':
+ return value.toString(16);
+ case mod == 'octal':
+ return value.toString(8);
+ case mod == 'binary':
+ return value.toString(2);
+ case mod == 'bytes10' || mod == 'bytes':
+ return formatBytes(value, 1000);
+ case mod == 'bytes2':
+ return formatBytes(value, 1024);
+ case mod == 'string':
+ return value.toString();
+ case mod == 'time':
+ return formatDuration(value);
+ case mod.startsWith('>='): {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_int_modifier(${mod})}`;
+
+ const check = Number(mod.replace('>=', ''));
+
+ if (Number.isNaN(check)) return `{unknown_int_modifier(${mod})}`;
+
+ if (_value) {
+ return value >= check
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return value >= check ? check_true : check_false;
+ }
+ case mod.startsWith('>'): {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_int_modifier(${mod})}`;
+
+ const check = Number(mod.replace('>', ''));
+
+ if (Number.isNaN(check)) return `{unknown_int_modifier(${mod})}`;
+
+ if (_value) {
+ return value > check
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return value > check ? check_true : check_false;
+ }
+ case mod.startsWith('='): {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_int_modifier(${mod})}`;
+
+ const check = Number(mod.replace('=', ''));
+
+ if (Number.isNaN(check)) return `{unknown_int_modifier(${mod})}`;
+
+ if (_value) {
+ return value == check
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return value == check ? check_true : check_false;
+ }
+ case mod.startsWith('<='): {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_int_modifier(${mod})}`;
+
+ const check = Number(mod.replace('<=', ''));
+
+ if (Number.isNaN(check)) return `{unknown_int_modifier(${mod})}`;
+
+ if (_value) {
+ return value <= check
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return value <= check ? check_true : check_false;
+ }
+ case mod.startsWith('<'): {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_int_modifier(${mod})}`;
+
+ const check = Number(mod.replace('<', ''));
+
+ if (Number.isNaN(check)) return `{unknown_int_modifier(${mod})}`;
+
+ if (_value) {
+ return value < check
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return value < check ? check_true : check_false;
+ }
+ default:
+ return `{unknown_int_modifier(${mod})}`;
+ }
+ } else if (typeof value === 'boolean') {
+ switch (true) {
+ case mod == 'istrue': {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_bool_modifier(${mod})}`;
+
+ if (_value) {
+ return value
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return value ? check_true : check_false;
+ }
+ case mod == 'isfalse': {
+ if (typeof check_true !== 'string' || typeof check_false !== 'string')
+ return `{unknown_bool_modifier(${mod})}`;
+
+ if (_value) {
+ return !value
+ ? this.parseString(check_true, _value) || check_true
+ : this.parseString(check_false, _value) || check_false;
+ }
+
+ return !value ? check_true : check_false;
+ }
+ default:
+ return `{unknown_bool_modifier(${mod})}`;
+ }
+ }
+
+ if (
+ typeof check_false == 'string' &&
+ (['>', '>=', '=', '<=', '<', '~', '$', '^'].some((modif) =>
+ mod.startsWith(modif)
+ ) ||
+ ['istrue', 'exists', 'isfalse'].includes(mod))
+ ) {
+ if (_value) return this.parseString(check_false, _value) || check_false;
+ return check_false;
+ }
+
+ return `{unknown_modifier(${mod})}`;
+ }
+
+ protected replaceCharsFromString(
+ str: string,
+ replace: string,
+ start: number,
+ end: number
+ ): string {
+ return str.slice(0, start) + replace + str.slice(end);
+ }
+}
diff --git a/packages/core/src/formatters/custom.ts b/packages/core/src/formatters/custom.ts
new file mode 100644
index 00000000..be11456f
--- /dev/null
+++ b/packages/core/src/formatters/custom.ts
@@ -0,0 +1,38 @@
+import { BaseFormatter, FormatterConfig } from './base';
+
+export class CustomFormatter extends BaseFormatter {
+ constructor(
+ nameTemplate: string,
+ descriptionTemplate: string,
+ addonName?: string
+ ) {
+ super(
+ {
+ name: nameTemplate,
+ description: descriptionTemplate,
+ },
+ addonName
+ );
+ }
+
+ public static fromConfig(
+ config: FormatterConfig,
+ addonName: string | undefined
+ ): CustomFormatter {
+ return new CustomFormatter(config.name, config.description, addonName);
+ }
+
+ public updateTemplate(
+ nameTemplate: string,
+ descriptionTemplate: string
+ ): void {
+ this.config = {
+ name: nameTemplate,
+ description: descriptionTemplate,
+ };
+ }
+
+ public getTemplate(): FormatterConfig {
+ return this.config;
+ }
+}
diff --git a/packages/core/src/formatters/index.ts b/packages/core/src/formatters/index.ts
new file mode 100644
index 00000000..56b981c1
--- /dev/null
+++ b/packages/core/src/formatters/index.ts
@@ -0,0 +1,41 @@
+export * from './base';
+export * from './predefined';
+export * from './custom';
+export * from './utils';
+
+import { BaseFormatter, FormatterConfig } from './base';
+import {
+ TorrentioFormatter,
+ TorboxFormatter,
+ GDriveFormatter,
+ LightGDriveFormatter,
+ MinimalisticGdriveFormatter,
+} from './predefined';
+import { CustomFormatter } from './custom';
+import { FormatterType } from '../utils/constants';
+
+export function createFormatter(
+ type: FormatterType,
+ config?: FormatterConfig,
+ addonName?: string
+): BaseFormatter {
+ switch (type) {
+ case 'torrentio':
+ return new TorrentioFormatter(addonName);
+ case 'torbox':
+ return new TorboxFormatter(addonName);
+ case 'gdrive':
+ return new GDriveFormatter(addonName);
+ case 'lightgdrive':
+ return new LightGDriveFormatter(addonName);
+ case 'minimalisticgdrive':
+ return new MinimalisticGdriveFormatter(addonName);
+ case 'custom':
+ if (!config) {
+ throw new Error('Config is required for custom formatter');
+ }
+ return CustomFormatter.fromConfig(config, addonName);
+ default:
+ throw new Error(`Unknown formatter type: ${type}`);
+ }
+}
diff --git a/packages/core/src/formatters/predefined.ts b/packages/core/src/formatters/predefined.ts
new file mode 100644
index 00000000..00752ac8
--- /dev/null
+++ b/packages/core/src/formatters/predefined.ts
@@ -0,0 +1,96 @@
+import { BaseFormatter, FormatterConfig } from './base';
+
+export class TorrentioFormatter extends BaseFormatter {
+ constructor(addonName?: string) {
+ super(
+ {
+ name: `
+{stream.proxied::istrue["🕵️♂️ "||""]}{stream.type::=p2p["[P2P] "||""]}{service.id::exists["[{service.shortName}"||""]}{service.cached::istrue["+] "||""]}{service.cached::isfalse[" download] "||""]}{addon.name} {stream.resolution::exists["{stream.resolution}"||"Unknown"]}
+{stream.visualTags::exists["{stream.visualTags::join(' | ')}"||""]}
+`,
+ description: `
+{stream.message::exists["ℹ️{stream.message}"||""]}
+{stream.folderName::exists["{stream.folderName}"||""]}
+{stream.filename::exists["{stream.filename}"||""]}
+{stream.size::>0["💾{stream.size::bytes2} "||""]}{stream.folderSize::>0["/ 💾{stream.folderSize::bytes2}"||""]}{stream.seeders::>=0["👤{stream.seeders} "||""]}{stream.age::exists["📅{stream.age} "||""]}{stream.indexer::exists["⚙️{stream.indexer}"||""]}
+{stream.languageEmojis::exists["{stream.languageEmojis::join( / ')}"||""]}
+`,
+ },
+ addonName
+ );
+ }
+}
+
+export class TorboxFormatter extends BaseFormatter {
+ constructor(addonName?: string) {
+ super(
+ {
+ name: `
+{stream.proxied::istrue["🕵️♂️ "||""]}{stream.type::=p2p["[P2P] "||""]}{addon.name}{stream.library::istrue[" (Your Media) "||""]}{service.cached::istrue[" (Instant "||""]}{service.cached::isfalse[" ("||""]}{service.id::exists["{service.shortName})"||""]}{stream.resolution::exists[" ({stream.resolution})"||""]}
+ `,
+ description: `
+Quality: {stream.quality::exists["{stream.quality}"||"Unknown"]}
+Name: {stream.filename::exists["{stream.filename}"||"Unknown"]}
+Size: {stream.size::>0["{stream.size::bytes} "||""]}{stream.folderSize::>0["/ {stream.folderSize::bytes} "||""]}{stream.indexer::exists["| Source: {stream.indexer} "||""]}{stream.duration::>0["| Duration: {stream.duration::time} "||""]}
+Language: {stream.languages::exists["{stream.languages::join(', ')}"||""]}
+Type: {stream.type::title}{stream.seeders::>=0[" | Seeders: {stream.seeders}"||""]}{stream.age::exists[" | Age: {stream.age}"||""]}
+{stream.message::exists["Message: {stream.message}"||""]}
+ `,
+ },
+ addonName
+ );
+ }
+}
+
+export class GDriveFormatter extends BaseFormatter {
+ constructor(addonName?: string) {
+ super(
+ {
+ name: `
+{stream.proxied::istrue["🕵️ "||""]}{stream.type::=p2p["[P2P] "||""]}{service.shortName::exists["[{service.shortName}"||""]}{service.cached::istrue["⚡] "||""]}{service.cached::isfalse["⏳] "||""]}{addon.name}{stream.library::istrue[" (Your Media)"||""]} {stream.resolution::exists["{stream.resolution}"||""]}{stream.regexMatched::exists[" ({stream.regexMatched})"||""]}
+ `,
+ description: `
+{stream.quality::exists["🎥 {stream.quality} "||""]}{stream.encode::exists["🎞️ {stream.encode} "||""]}{stream.releaseGroup::exists["🏷️ {stream.releaseGroup}"||""]}
+{stream.visualTags::exists["📺 {stream.visualTags::join(' | ')} "||""]}{stream.audioTags::exists["🎧 {stream.audioTags::join(' | ')} "||""]}{stream.audioChannels::exists["🔊 {stream.audioChannels::join(' | ')}"||""]}
+{stream.size::>0["📦 {stream.size::bytes} "||""]}{stream.folderSize::>0["/ 📦 {stream.folderSize::bytes}"||""]}{stream.duration::>0["⏱️ {stream.duration::time} "||""]}{stream.seeders::>0["👥 {stream.seeders} "||""]}{stream.age::exists["📅 {stream.age} "||""]}{stream.indexer::exists["🔍 {stream.indexer}"||""]}
+{stream.languages::exists["🌎 {stream.languages::join(' | ')}"||""]}
+{stream.filename::exists["📁"||""]} {stream.folderName::exists["{stream.folderName}/"||""]}{stream.filename::exists["{stream.filename}"||""]}
+{stream.message::exists["ℹ️ {stream.message}"||""]}
+ `,
+ },
+ addonName
+ );
+ }
+}
+
+export class LightGDriveFormatter extends BaseFormatter {
+ constructor(addonName?: string) {
+ super(
+ {
+ name: `
+{stream.proxied::istrue["🕵️ "||""]}{stream.type::=p2p["[P2P] "||""]}{service.shortName::exists["[{service.shortName}"||""]}{stream.library::istrue["☁️"||""]}{service.cached::istrue["⚡] "||""]}{service.cached::isfalse["⏳] "||""]}{addon.name}{stream.resolution::exists[" {stream.resolution}"||""]}{stream.regexMatched::exists[" ({stream.regexMatched})"||""]}
+`,
+ description: `
+{stream.title::exists["📁 {stream.title}"||""]}{stream.year::exists[" ({stream.year})"||""]}{stream.season::>=0[" S"||""]}{stream.season::<=9["0"||""]}{stream.season::>0["{stream.season}"||""]}{stream.episode::>=0[" • E"||""]}{stream.episode::<=9["0"||""]}{stream.episode::>0["{stream.episode}"||""]}
+{stream.quality::exists["🎥 {stream.quality} "||""]}{stream.encode::exists["🎞️ {stream.encode} "||""]}{stream.releaseGroup::exists["🏷️ {stream.releaseGroup}"||""]}
+{stream.visualTags::exists["📺 {stream.visualTags::join(' • ')} "||""]}{stream.audioTags::exists["🎧 {stream.audioTags::join(' • ')} "||""]}{stream.audioChannels::exists["🔊 {stream.audioChannels::join(' • ')}"||""]}
+{stream.size::>0["📦 {stream.size::bytes} "||""]}{stream.folderSize::>0["/ 📦 {stream.folderSize::bytes}"||""]}{stream.duration::>0["⏱️ {stream.duration::time} "||""]}{stream.age::exists["📅 {stream.age} "||""]}{stream.indexer::exists["🔍 {stream.indexer}"||""]}
+{stream.languageEmojis::exists["🌐 {stream.languageEmojis::join(' / ')}"||""]}
+ `,
+ },
+ addonName
+ );
+ }
+}
+
+export class MinimalisticGdriveFormatter extends BaseFormatter {
+ constructor(addonName?: string) {
+ super(
+ {
+ name: '{stream.title} {stream.quality}',
+ description: '{stream.size::bytes} {stream.seeders} seeders',
+ },
+ addonName
+ );
+ }
+}
diff --git a/packages/formatters/src/utils.ts b/packages/core/src/formatters/utils.ts
similarity index 94%
rename from packages/formatters/src/utils.ts
rename to packages/core/src/formatters/utils.ts
index 5d498f3b..0085c09b 100644
--- a/packages/formatters/src/utils.ts
+++ b/packages/core/src/formatters/utils.ts
@@ -1,7 +1,9 @@
-export function formatSize(bytes: number): string {
+export function formatBytes(bytes: number, k: 1024 | 1000): string {
if (bytes === 0) return '0 B';
- const k = 1024;
- const sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB'];
+ const sizes =
+ k === 1024
+ ? ['B', 'KiB', 'MiB', 'GiB', 'TiB']
+ : ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
new file mode 100644
index 00000000..0aaec49c
--- /dev/null
+++ b/packages/core/src/index.ts
@@ -0,0 +1,7 @@
+export * from './utils';
+export * from './db';
+export * from './main';
+export * from './parser';
+export * from './formatters';
+export * from './transformers';
+export { PresetManager } from './presets';
diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts
new file mode 100644
index 00000000..6aa131cb
--- /dev/null
+++ b/packages/core/src/main.ts
@@ -0,0 +1,2799 @@
+import {
+ Addon,
+ Manifest,
+ Resource,
+ StrictManifestResource,
+ UserData,
+ UserRepository,
+} from './db';
+import {
+ AUDIO_TAGS,
+ constants,
+ createLogger,
+ Env,
+ getSimpleTextHash,
+ getTimeTakenSincePoint,
+ makeRequest,
+ StreamType,
+ TYPES,
+ VISUAL_TAGS,
+ TMDBMetadata,
+ PossibleRecursiveRequestError,
+ decryptString,
+ maskSensitiveInfo,
+} from './utils';
+import { Wrapper } from './wrapper';
+import { PresetManager } from './presets';
+import {
+ AddonCatalog,
+ Meta,
+ MetaPreview,
+ ParsedStream,
+ SortCriterion,
+ Stream,
+ Subtitle,
+} from './db/schemas';
+import { createProxy } from './proxy';
+import { createFormatter } from './formatters';
+import {
+ compileRegex,
+ formRegexFromKeywords,
+ safeRegexTest,
+} from './utils/regex';
+import { isMatch } from 'super-regex';
+import { ConditionParser } from './parser/conditions';
+import { RPDB } from './utils/rpdb';
+import { FeatureControl } from './utils/feature';
+const logger = createLogger('core');
+
+export interface AIOStreamsError {
+ title?: string;
+ description?: string;
+}
+
+export interface AIOStreamsResponse {
+ success: boolean;
+ data: T;
+ errors: AIOStreamsError[];
+}
+
+export class AIOStreams {
+ private readonly userData: UserData;
+ private manifests: Record;
+ private supportedResources: Record;
+ private finalResources: StrictManifestResource[] = [];
+ private finalCatalogs: Manifest['catalogs'] = [];
+ private finalAddonCatalogs: Manifest['addonCatalogs'] = [];
+ private isInitialised: boolean = false;
+ private addons: Addon[] = [];
+ private skipFailedAddons: boolean = true;
+ private addonInitialisationErrors: {
+ addon: Addon;
+ error: string;
+ }[] = [];
+
+ constructor(userData: UserData, skipFailedAddons: boolean = true) {
+ this.addonInitialisationErrors = [];
+ this.userData = userData;
+ this.manifests = {};
+ this.supportedResources = {};
+ this.skipFailedAddons = skipFailedAddons;
+ }
+
+ public async initialise(): Promise {
+ if (this.isInitialised) return this;
+ await this.applyPresets();
+ await this.assignPublicIps();
+ await this.fetchManifests();
+ await this.fetchResources();
+ this.isInitialised = true;
+ return this;
+ }
+
+ private checkInitialised() {
+ if (!this.isInitialised) {
+ throw new Error(
+ 'AIOStreams is not initialised. Call initialise() first.'
+ );
+ }
+ }
+
+ public async getStreams(
+ id: string,
+ type: string,
+ preCaching: boolean = false
+ ): Promise> {
+ logger.info(`Handling stream request`, { type, id });
+
+ // step 1
+ // get the public IP of the requesting user, using the proxy server if configured
+ // if a proxy server is configured, and we fail to get the IP, return an error.
+ // however, note that some addons may not be configured to use a proxy,
+ // so we should attach an IP to each addon depending on if it would be using the proxy or not.
+
+ // step 2
+ // get all parsed stream objects and errors from all addons that have the stream resource.
+ // and that support the type and match the id prefix
+
+ const { streams, errors } = await this.getStreamsFromAddons(type, id);
+
+ logger.info(
+ `Received ${streams.length} streams and ${errors.length} errors`
+ );
+
+ // step 3
+ // apply all filters to the streams.
+
+ const filteredStreams = await this.applyFilters(streams, type, id);
+
+ // step 4
+ // deduplicate streams based on the depuplicatoroptions
+
+ const deduplicatedStreams = this.deduplicateStreams(filteredStreams);
+
+ // step 5
+ // sort the streams based on the sort criteria.
+
+ await this.precomputeSortRegexes(deduplicatedStreams);
+
+ const sortedStreams = this.sortStreams(deduplicatedStreams, type)
+ // remove HDR+DV from visual tags after filtering/sorting
+ .map((stream) => {
+ if (stream.parsedFile?.visualTags?.includes('HDR+DV')) {
+ stream.parsedFile.visualTags = stream.parsedFile.visualTags.filter(
+ (tag) => tag !== 'HDR+DV'
+ );
+ }
+ return stream;
+ });
+
+ // step 6
+ // limit the number of streams based on the limit criteria.
+
+ const limitedStreams = this.limitStreams(sortedStreams);
+
+ // step 7
+ // proxify streaming links if a proxy is provided
+
+ const proxifiedStreams = this.applyModifications(
+ await this.proxifyStreams(limitedStreams)
+ );
+
+ // step 8
+ // if this.userData.precacheNextEpisode is true, start a new thread to request the next episode, check if
+ // all provider streams are uncached, and only if so, then send a request to the first uncached stream in the list.
+ if (this.userData.precacheNextEpisode && !preCaching) {
+ setImmediate(() => {
+ this.precacheNextEpisode(type, id).catch((error) => {
+ logger.error('Error during precaching:', {
+ error: error instanceof Error ? error.message : String(error),
+ type,
+ id,
+ });
+ });
+ });
+ }
+
+ // step 9
+ // return the final list of streams, followed by the error streams.
+ logger.info(
+ `Returning ${proxifiedStreams.length} streams and ${errors.length} errors`
+ );
+ return {
+ success: true,
+ data: proxifiedStreams,
+ errors: errors,
+ };
+ }
+
+ private async precacheNextEpisode(type: string, id: string) {
+ const seasonEpisodeRegex = /:(\d+):(\d+)$/;
+ const match = id.match(seasonEpisodeRegex);
+ if (!match) {
+ return;
+ }
+ const season = match[1];
+ const episode = match[2];
+ const titleId = id.replace(seasonEpisodeRegex, '');
+ const nextEpisodeId = `${titleId}:${season}:${Number(episode) + 1}`;
+ logger.info(`Pre-caching next episode of ${titleId}`, {
+ season,
+ episode,
+ nextEpisode: Number(episode) + 1,
+ nextEpisodeId,
+ });
+ const nextStreamsResponse = await this.getStreams(
+ nextEpisodeId,
+ type,
+ true
+ );
+ if (nextStreamsResponse.success) {
+ const nextStreams = nextStreamsResponse.data;
+ const serviceStreams = nextStreams.filter((stream) => stream.service);
+ if (serviceStreams.every((stream) => stream.service?.cached === false)) {
+ const firstUncachedStream = serviceStreams.find(
+ (stream) => stream.service?.cached === false
+ );
+ if (firstUncachedStream && firstUncachedStream.url) {
+ try {
+ const wrapper = new Wrapper(firstUncachedStream.addon);
+ logger.debug(
+ `The following stream was selected for precaching:\n${firstUncachedStream.originalDescription}`
+ );
+ const response = await wrapper.makeRequest(firstUncachedStream.url);
+ if (!response.ok) {
+ throw new Error(`${response.status} ${response.statusText}`);
+ }
+ logger.debug(`Response: ${response.status} ${response.statusText}`);
+ } catch (error) {
+ logger.error(`Error pinging url of first uncached stream`, {
+ error: error instanceof Error ? error.message : String(error),
+ });
+ }
+ }
+ }
+ }
+ }
+
+ public async getCatalog(
+ type: string,
+ id: string,
+ extras?: string
+ ): Promise> {
+ // step 1
+ // get the addon index from the id
+ logger.info(`Handling catalog request`, { type, id, extras });
+ const start = Date.now();
+ const addonIndex = id.split('.', 2)[0];
+ const addon = this.getAddon(Number(addonIndex));
+ if (!addon) {
+ logger.error(`Addon ${addonIndex} not found`);
+ return {
+ success: false,
+ data: [],
+ errors: [
+ {
+ title: `Addon ${addonIndex} not found`,
+ description: 'Addon not found',
+ },
+ ],
+ };
+ }
+
+ // step 2
+ // get the actual catalog id from the id
+ const actualCatalogId = id.split('.').slice(1).join('.');
+ // step 3
+ // get the catalog from the addon
+ let catalog;
+ try {
+ catalog = await new Wrapper(addon).getCatalog(
+ type,
+ actualCatalogId,
+ extras
+ );
+ } catch (error) {
+ await this.handlePossibleRecursiveError(error);
+ return {
+ success: false,
+ data: [],
+ errors: [
+ {
+ title: `[❌] ${addon.name}`,
+ description: error instanceof Error ? error.message : String(error),
+ },
+ ],
+ };
+ }
+
+ logger.info(
+ `Received catalog ${actualCatalogId} of type ${type} from ${addon.name} in ${getTimeTakenSincePoint(start)}`
+ );
+
+ // apply catalog modifications
+ if (this.userData.catalogModifications) {
+ const modification = this.userData.catalogModifications.find(
+ (mod) => mod.id === id && mod.type === type
+ );
+ if (modification) {
+ if (modification.shuffle && !(extras && extras.includes('search'))) {
+ // shuffle the catalog array if it is not a search
+ catalog = catalog.sort(() => Math.random() - 0.5);
+ }
+ if (modification.rpdb && this.userData.rpdbApiKey) {
+ const rpdb = new RPDB(this.userData.rpdbApiKey);
+ catalog = catalog.map((item) => {
+ const posterUrl = rpdb.getPosterUrl(
+ type,
+ (item as any).imdb_id || item.id
+ );
+ if (posterUrl) {
+ item.poster = posterUrl;
+ }
+ return item;
+ });
+ }
+ }
+ }
+
+ if (this.userData.enhancePosters) {
+ catalog = catalog.map((item) => {
+ if (Math.random() < 0.2) {
+ item.poster = Buffer.from(
+ constants.DEFAULT_POSTERS[
+ Math.floor(Math.random() * constants.DEFAULT_POSTERS.length)
+ ],
+ 'base64'
+ ).toString('utf-8');
+ }
+ return item;
+ });
+ }
+
+ // step 4
+ return {
+ success: true,
+ data: catalog,
+ errors: [],
+ };
+ }
+
+ public async getMeta(
+ type: string,
+ id: string
+ ): Promise> {
+ logger.info(`Handling meta request`, { type, id });
+ // step 1
+ // First try to find an addon that has a matching idPrefix
+ for (const [index, resources] of Object.entries(this.supportedResources)) {
+ const resource = resources.find(
+ (r) =>
+ r.name === 'meta' &&
+ r.types.includes(type) &&
+ r.idPrefixes?.some((prefix) => id.startsWith(prefix))
+ );
+ if (resource) {
+ const addon = this.getAddon(Number(index));
+ logger.info(`Found addon with matching id prefix for meta resource`, {
+ addonName: addon.name,
+ addonIndex: index,
+ });
+ try {
+ const meta = await new Wrapper(addon).getMeta(type, id);
+ return {
+ success: true,
+ data: meta,
+ errors: [],
+ };
+ } catch (error) {
+ await this.handlePossibleRecursiveError(error);
+ logger.error(`Error getting meta from addon ${addon.name}`, {
+ error: error instanceof Error ? error.message : String(error),
+ });
+ return {
+ success: false,
+ data: null,
+ errors: [
+ {
+ title: `[❌] ${addon.name}`,
+ description:
+ error instanceof Error ? error.message : String(error),
+ },
+ ],
+ };
+ }
+ }
+ }
+
+ // step 2
+ // If no matching prefix found, use any addon that supports meta for this type
+ for (const [index, resources] of Object.entries(this.supportedResources)) {
+ const resource = resources.find(
+ (r) => r.name === 'meta' && r.types.includes(type)
+ );
+ if (resource) {
+ const addon = this.getAddon(Number(index));
+ logger.info(`Using fallback addon for meta resource`, {
+ addonName: addon.name,
+ addonIndex: index,
+ });
+ try {
+ const meta = await new Wrapper(addon).getMeta(type, id);
+ return {
+ success: true,
+ data: meta,
+ errors: [],
+ };
+ } catch (error) {
+ await this.handlePossibleRecursiveError(error);
+ logger.error(`Error getting meta from addon ${addon.name}`, {
+ error: error instanceof Error ? error.message : String(error),
+ });
+ return {
+ success: false,
+ data: null,
+ errors: [
+ {
+ title: `[❌] ${addon.name}`,
+ description:
+ error instanceof Error ? error.message : String(error),
+ },
+ ],
+ };
+ }
+ }
+ }
+
+ logger.error(`No addon found supporting meta resource for type ${type}`);
+ throw new Error(`No addon found supporting meta resource for type ${type}`);
+ }
+
+ // subtitle resource
+ public async getSubtitles(
+ type: string,
+ id: string,
+ extras?: string
+ ): Promise> {
+ logger.info(`getSubtitles: ${id}`);
+
+ // Find all addons that support subtitles for this type and id prefix
+ const supportedAddons = [];
+ for (const [addonIndex, addonResources] of Object.entries(
+ this.supportedResources
+ )) {
+ const resource = addonResources.find(
+ (r) =>
+ r.name === 'subtitles' &&
+ r.types.includes(type) &&
+ (r.idPrefixes
+ ? r.idPrefixes.some((prefix) => id.startsWith(prefix))
+ : true)
+ );
+ if (resource) {
+ const addon = this.getAddon(Number(addonIndex));
+ if (addon) {
+ supportedAddons.push(addon);
+ }
+ }
+ }
+
+ // Request subtitles from all supported addons in parallel
+ let errors: AIOStreamsError[] = this.addonInitialisationErrors.map(
+ (error) => ({
+ title: `[❌] ${error.addon.identifyingName}`,
+ description: error.error,
+ })
+ );
+ let allSubtitles: Subtitle[] = [];
+
+ await Promise.all(
+ supportedAddons.map(async (addon) => {
+ try {
+ const subtitles = await new Wrapper(addon).getSubtitles(
+ type,
+ id,
+ extras
+ );
+ if (subtitles) {
+ allSubtitles.push(...subtitles);
+ }
+ } catch (error) {
+ await this.handlePossibleRecursiveError(error);
+ errors.push({
+ title: `[❌] ${addon.identifyingName}`,
+ description: error instanceof Error ? error.message : String(error),
+ });
+ }
+ })
+ );
+
+ return {
+ success: true,
+ data: allSubtitles,
+ errors: errors,
+ };
+ }
+
+ // addon_catalog resource
+ public async getAddonCatalog(
+ type: string,
+ id: string
+ ): Promise> {
+ logger.info(`getAddonCatalog: ${id}`);
+ // step 1
+ // get the addon index from the id
+ const addonIndex = id.split('.', 2)[0];
+ const addon = this.getAddon(Number(addonIndex));
+ if (!addon) {
+ return {
+ success: false,
+ data: [],
+ errors: [
+ {
+ title: `Addon ${addonIndex} not found`,
+ description: 'Addon not found',
+ },
+ ],
+ };
+ }
+
+ // step 2
+ // get the actual addon catalog id from the id
+ const actualAddonCatalogId = id.split('.').slice(1).join('.');
+
+ // step 3
+ // get the addon catalog from the addon
+ let addonCatalogs: AddonCatalog[] = [];
+ try {
+ addonCatalogs = await new Wrapper(addon).getAddonCatalog(
+ type,
+ actualAddonCatalogId
+ );
+ } catch (error) {
+ await this.handlePossibleRecursiveError(error);
+ return {
+ success: false,
+ data: [],
+ errors: [
+ {
+ title: `[❌] ${addon.identifyingName}`,
+ description: error instanceof Error ? error.message : String(error),
+ },
+ ],
+ };
+ }
+ // step 4
+ return {
+ success: true,
+ data: addonCatalogs,
+ errors: [],
+ };
+ }
+ // converts all addons to
+ private async applyPresets() {
+ if (!this.userData.presets) {
+ return;
+ }
+
+ for (const preset of this.userData.presets.filter((p) => p.enabled)) {
+ const addons = await PresetManager.fromId(preset.id).generateAddons(
+ this.userData,
+ preset.options
+ );
+
+ this.addons.push(
+ ...addons.map((a) => ({
+ ...a,
+ id: JSON.stringify(preset),
+ }))
+ );
+ }
+
+ if (this.addons.length > Env.MAX_ADDONS) {
+ throw new Error(
+ `Your current configuration requires ${this.addons.length} addons, but the maximum allowed is ${Env.MAX_ADDONS}. Please reduce the number of addons, or increase it in the environment variables.`
+ );
+ }
+ }
+
+ private async fetchManifests() {
+ this.manifests = Object.fromEntries(
+ await Promise.all(
+ this.addons.map(async (addon, index) => {
+ try {
+ this.validateAddon(addon);
+ return [index, await new Wrapper(addon).getManifest()];
+ } catch (error: any) {
+ await this.handlePossibleRecursiveError(error);
+ if (this.skipFailedAddons) {
+ this.addonInitialisationErrors.push({
+ addon: addon,
+ error: error.message,
+ });
+ logger.error(`${error.message}, skipping`);
+ return [index, null];
+ }
+ throw error;
+ }
+ })
+ )
+ );
+ }
+
+ private async fetchResources() {
+ for (const [index, manifest] of Object.entries(this.manifests)) {
+ if (!manifest) continue;
+
+ // Convert string resources to StrictManifestResource objects
+ const addonResources = manifest.resources.map((resource) => {
+ if (typeof resource === 'string') {
+ return {
+ name: resource as Resource,
+ types: manifest.types,
+ idPrefixes: manifest.idPrefixes,
+ };
+ }
+ return resource;
+ });
+
+ const addon = this.addons[Number(index)];
+
+ logger.verbose(
+ `Determined that ${addon.identifyingName} (Index: ${index}) has support for the following resources: ${JSON.stringify(
+ addonResources
+ )}`
+ );
+
+ // Filter and merge resources
+ for (const resource of addonResources) {
+ if (
+ addon.resources &&
+ addon.resources.length > 0 &&
+ !addon.resources.includes(resource.name)
+ ) {
+ continue;
+ }
+
+ const existing = this.finalResources.find(
+ (r) => r.name === resource.name
+ );
+ if (existing) {
+ existing.types = [...new Set([...existing.types, ...resource.types])];
+ if (resource.idPrefixes) {
+ existing.idPrefixes = existing.idPrefixes || [];
+ existing.idPrefixes = [
+ ...new Set([...existing.idPrefixes, ...resource.idPrefixes]),
+ ];
+ }
+ } else {
+ this.finalResources.push({
+ ...resource,
+ idPrefixes: resource.idPrefixes
+ ? [...resource.idPrefixes]
+ : undefined,
+ });
+ }
+ }
+
+ // Add catalogs with prefixed IDs (ensure to check that if addon.resources is defined and does not have catalog
+ // then we do not add the catalogs)
+
+ if (
+ !addon.resources?.length ||
+ (addon.resources && addon.resources.includes('catalog'))
+ ) {
+ this.finalCatalogs.push(
+ ...manifest.catalogs.map((catalog) => ({
+ ...catalog,
+ id: `${index}.${catalog.id}`,
+ }))
+ );
+ }
+
+ // add all addon catalogs, prefixing id with index
+ if (manifest.addonCatalogs) {
+ this.finalAddonCatalogs!.push(
+ ...(manifest.addonCatalogs || []).map((catalog) => ({
+ ...catalog,
+ id: `${index}.${catalog.id}`,
+ }))
+ );
+ }
+
+ this.supportedResources[Number(index)] = addonResources;
+ }
+
+ logger.verbose(
+ `Parsed all catalogs and determined the following catalogs: ${JSON.stringify(
+ this.finalCatalogs.map((c) => ({
+ id: c.id,
+ name: c.name,
+ type: c.type,
+ }))
+ )}`
+ );
+
+ logger.verbose(
+ `Parsed all addon catalogs and determined the following catalogs: ${JSON.stringify(
+ this.finalAddonCatalogs?.map((c) => ({
+ id: c.id,
+ name: c.name,
+ type: c.type,
+ }))
+ )}`
+ );
+
+ logger.verbose(
+ `Parsed all resources and determined the following resources: ${JSON.stringify(
+ this.finalResources.map((r) => ({
+ name: r.name,
+ types: r.types,
+ idPrefixes: r.idPrefixes,
+ }))
+ )}`
+ );
+
+ if (this.userData.catalogModifications) {
+ this.finalCatalogs = this.finalCatalogs
+ // Sort catalogs based on catalogModifications order, with non-modified catalogs at the end
+ .sort((a, b) => {
+ const aModIndex = this.userData.catalogModifications!.findIndex(
+ (mod) => mod.id === a.id && mod.type === a.type
+ );
+ const bModIndex = this.userData.catalogModifications!.findIndex(
+ (mod) => mod.id === b.id && mod.type === b.type
+ );
+
+ // If neither catalog is in modifications, maintain original order
+ if (aModIndex === -1 && bModIndex === -1) {
+ return (
+ this.finalCatalogs.indexOf(a) - this.finalCatalogs.indexOf(b)
+ );
+ }
+
+ // If only one catalog is in modifications, it should come first
+ if (aModIndex === -1) return 1;
+ if (bModIndex === -1) return -1;
+
+ // If both are in modifications, sort by their order in modifications
+ return aModIndex - bModIndex;
+ })
+ // filter out any catalogs that are disabled
+ .filter((catalog) => {
+ const modification = this.userData.catalogModifications!.find(
+ (mod) => mod.id === catalog.id && mod.type === catalog.type
+ );
+ return modification?.enabled !== false; // only if explicity disabled i.e. enabled is true or undefined
+ })
+ // rename any catalogs if necessary and apply the onlyOnDiscover modification
+ .map((catalog) => {
+ const modification = this.userData.catalogModifications!.find(
+ (mod) => mod.id === catalog.id && mod.type === catalog.type
+ );
+ if (modification?.name) {
+ catalog.name = modification.name;
+ }
+ if (modification?.onlyOnDiscover) {
+ // look in the extra list for a extra with name 'genre', and set 'isRequired' to true
+ const genreExtra = catalog.extra?.find((e) => e.name === 'genre');
+ if (genreExtra) {
+ genreExtra.isRequired = true;
+ }
+ }
+ return catalog;
+ });
+ }
+ }
+
+ public getResources(): StrictManifestResource[] {
+ this.checkInitialised();
+ return this.finalResources;
+ }
+
+ public getCatalogs(): Manifest['catalogs'] {
+ this.checkInitialised();
+ return this.finalCatalogs;
+ }
+
+ public getAddonCatalogs(): Manifest['addonCatalogs'] {
+ this.checkInitialised();
+ return this.finalAddonCatalogs;
+ }
+
+ public getAddon(index: number): Addon {
+ return this.addons[index];
+ }
+
+ private shouldProxyStream(stream: ParsedStream): boolean {
+ const streamService = stream.service ? stream.service.id : 'none';
+ const proxy = this.userData.proxy;
+ if (!stream.url || !proxy?.enabled) {
+ return false;
+ }
+
+ const proxyAddon =
+ !proxy.proxiedAddons?.length ||
+ proxy.proxiedAddons.includes(stream.addon.id || '');
+ const proxyService =
+ !proxy.proxiedServices?.length ||
+ proxy.proxiedServices.includes(streamService);
+
+ if (proxy.enabled && proxyAddon && proxyService) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private async getProxyIp() {
+ let userIp = this.userData.ip;
+ const PRIVATE_IP_REGEX =
+ /^(::1|::ffff:(10|127|192|172)\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})|10\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})|127\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})|192\.168\.(\d{1,3})\.(\d{1,3})|172\.(1[6-9]|2[0-9]|3[0-1])\.(\d{1,3})\.(\d{1,3}))$/;
+
+ if (userIp && PRIVATE_IP_REGEX.test(userIp)) {
+ userIp = undefined;
+ }
+ if (!this.userData.proxy) {
+ return userIp;
+ }
+
+ const proxy = createProxy(this.userData.proxy);
+ if (proxy.getConfig().enabled) {
+ userIp = await this.retryGetIp(
+ () => proxy.getPublicIp(),
+ 'Proxy public IP'
+ );
+ }
+ return userIp;
+ }
+
+ private async retryGetIp(
+ getter: () => Promise,
+ label: string,
+ maxRetries: number = 3
+ ): Promise {
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
+ try {
+ const result = await getter();
+ if (result) {
+ return result;
+ }
+ } catch (error) {
+ logger.warn(
+ `Failed to get ${label}, retrying... (${attempt}/${maxRetries})`
+ );
+ }
+ }
+ throw new Error(`Failed to get ${label} after ${maxRetries} attempts`);
+ }
+ // stream utility functions
+ private async assignPublicIps() {
+ let userIp = this.userData.ip;
+ let proxyIp = undefined;
+ if (this.userData.proxy && this.userData.proxy.enabled) {
+ proxyIp = await this.getProxyIp();
+ }
+ for (const addon of this.addons) {
+ const proxy =
+ this.userData.proxy &&
+ (!this.userData.proxy?.proxiedAddons?.length ||
+ this.userData.proxy.proxiedAddons.includes(addon.id || ''));
+ logger.debug(
+ `Using ${proxy ? 'proxy' : 'user'} ip for ${addon.identifyingName}: ${
+ proxy
+ ? maskSensitiveInfo(proxyIp ?? 'none')
+ : maskSensitiveInfo(userIp ?? 'none')
+ }`
+ );
+ if (proxy) {
+ addon.ip = proxyIp;
+ } else {
+ addon.ip = userIp;
+ }
+ }
+ }
+
+ private async getStreamsFromAddons(type: string, id: string) {
+ // get a list of all addons that support the stream resource with the given type and id.
+ const supportedAddons = [];
+ for (const [index, addonResources] of Object.entries(
+ this.supportedResources
+ )) {
+ const resource = addonResources.find(
+ (r) =>
+ r.name === 'stream' &&
+ r.types.includes(type) &&
+ (r.idPrefixes
+ ? r.idPrefixes?.some((prefix) => id.startsWith(prefix))
+ : true) // if no id prefixes are defined, assume it supports all IDs
+ );
+ if (resource) {
+ const addon = this.getAddon(Number(index));
+ if (addon) {
+ supportedAddons.push(addon);
+ }
+ }
+ }
+
+ logger.info(
+ `Found ${supportedAddons.length} addons that support the stream resource`,
+ {
+ supportedAddons: supportedAddons.map((a) => a.name),
+ }
+ );
+
+ let errors: AIOStreamsError[] = this.addonInitialisationErrors.map((e) => ({
+ title: `[❌] ${e.addon.identifyingName}`,
+ description: e.error,
+ }));
+ let parsedStreams: ParsedStream[] = [];
+ let totalTimeTaken = 0;
+ let previousGroupStreams: ParsedStream[] = [];
+ let previousGroupTimeTaken = 0;
+
+ // Helper function to fetch streams from an addon and log summary
+ const fetchFromAddon = async (addon: Addon) => {
+ let summaryMsg = '';
+ const start = Date.now();
+ try {
+ this.validateAddon(addon);
+ const streams = await new Wrapper(addon).getStreams(type, id);
+ // filter out error type streams and put them in errors instead
+ const errorStreams = streams.filter(
+ (s) => s.type === constants.ERROR_STREAM_TYPE
+ );
+ if (errorStreams.length > 0) {
+ logger.error(
+ `Found ${errorStreams.length} error streams from ${addon.identifyingName}`,
+ {
+ errorStreams: errorStreams.map((s) => s.error?.title),
+ }
+ );
+ errors.push(
+ ...errorStreams.map((s) => ({
+ title: `[❌] ${s.error?.title || addon.identifyingName}`,
+ description: s.error?.description || 'Unknown error',
+ }))
+ );
+ }
+
+ parsedStreams.push(
+ ...streams.filter((s) => s.type !== constants.ERROR_STREAM_TYPE)
+ );
+ // const errorStreams = streams.filter((s) => s.type === constants.ERROR_STREAM_TYPE);
+ // parsedStreams.push(...streams.filter((s) => s.type !== constants.ERROR_STREAM_TYPE));
+ // errors.push(...errorStreams.map((s) => ({
+ // addon: addon.identifyingName,
+ // error: s.error?.description || 'Unknown error',
+ // })));
+
+ summaryMsg = `
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+ ${errorStreams.length > 0 ? '🟠' : '🟢'} [${addon.identifyingName}] Scrape Summary
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+ ✔ Status : ${errorStreams.length > 0 ? 'PARTIAL SUCCESS' : 'SUCCESS'}
+ 📦 Streams : ${streams.length}
+${errorStreams.length > 0 ? ` ❌ Errors : ${errorStreams.map((s) => ` • ${s.error?.title || 'Unknown error'}: ${s.error?.description || 'No description'}`).join('\n')}` : ''}
+ 📋 Details : ${
+ errorStreams.length > 0
+ ? `Found errors:\n${errorStreams.map((s) => ` • ${s.error?.title || 'Unknown error'}: ${s.error?.description || 'No description'}`).join('\n')}`
+ : 'Successfully fetched streams.'
+ }
+ ⏱️ Time : ${getTimeTakenSincePoint(start)}
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`;
+ return {
+ success: true as const,
+ streams,
+ timeTaken: Date.now() - start,
+ };
+ } catch (error) {
+ await this.handlePossibleRecursiveError(error);
+ const errMsg = error instanceof Error ? error.message : String(error);
+ errors.push({
+ title: `[❌] ${addon.identifyingName}`,
+ description: errMsg,
+ });
+ summaryMsg = `
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+ 🔴 [${addon.identifyingName}] Scrape Summary
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+ ✖ Status : FAILED
+ 🚫 Error : ${errMsg}
+ ⏱️ Time : ${getTimeTakenSincePoint(start)}
+━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`;
+ return { success: false as const, error: errMsg, timeTaken: 0 };
+ } finally {
+ logger.info(summaryMsg);
+ }
+ };
+
+ // Helper function to fetch from a group of addons and track time
+ const fetchFromGroup = async (addons: Addon[]) => {
+ const groupStart = Date.now();
+ const results = await Promise.all(addons.map(fetchFromAddon));
+ const groupTime = Date.now() - groupStart;
+ return {
+ results,
+ totalTime: groupTime,
+ streams: results.flatMap((r) =>
+ r.success ? r.streams : []
+ ) as ParsedStream[],
+ };
+ };
+
+ // If groups are configured, handle group-based fetching
+ if (this.userData.groups && this.userData.groups.length > 0) {
+ // Always fetch from first group
+ const firstGroupAddons = supportedAddons.filter(
+ (addon) =>
+ addon.id && this.userData.groups![0].addons.includes(addon.id)
+ );
+
+ logger.info(
+ `Fetching streams from first group with ${firstGroupAddons.length} addons`
+ );
+
+ // Fetch streams from first group
+ const firstGroupResult = await fetchFromGroup(firstGroupAddons);
+ totalTimeTaken = firstGroupResult.totalTime;
+ previousGroupStreams = firstGroupResult.streams;
+ previousGroupTimeTaken = firstGroupResult.totalTime;
+
+ // For each subsequent group, evaluate condition and fetch if true
+ for (let i = 1; i < this.userData.groups.length; i++) {
+ const group = this.userData.groups[i];
+
+ // Skip if no condition or addons
+ if (!group.condition || !group.addons.length) continue;
+
+ try {
+ const parser = new ConditionParser(
+ previousGroupStreams,
+ parsedStreams,
+ previousGroupTimeTaken,
+ totalTimeTaken,
+ type
+ );
+ const shouldFetch = await parser.parse(group.condition);
+ if (shouldFetch) {
+ logger.info(`Condition met for group ${i + 1}, fetching streams`);
+
+ const groupAddons = supportedAddons.filter(
+ (addon) => addon.id && group.addons.includes(addon.id)
+ );
+
+ const groupResult = await fetchFromGroup(groupAddons);
+ totalTimeTaken += groupResult.totalTime;
+ previousGroupStreams = groupResult.streams;
+ previousGroupTimeTaken = groupResult.totalTime;
+ } else {
+ logger.info(
+ `Condition not met for group ${i + 1}, skipping remaining groups`
+ );
+ // if we meet a group whose condition is not met, we do not need to fetch from any subsequent groups
+ break;
+ }
+ } catch (error) {
+ logger.error(`Error evaluating condition for group ${i}:`, error);
+ continue;
+ }
+ }
+ } else {
+ // If no groups configured, fetch from all addons in parallel
+ const result = await fetchFromGroup(supportedAddons);
+ totalTimeTaken = result.totalTime;
+ }
+
+ return { streams: parsedStreams, errors };
+ }
+
+ private validateAddon(addon: Addon) {
+ if (this.userData.uuid && addon.manifestUrl.includes(this.userData.uuid)) {
+ logger.warn(
+ `${this.userData.uuid} detected to be trying to cause infinite self scraping`
+ );
+ throw new Error(
+ `${addon.identifyingName} appears to be trying to scrape the current user's AIOStreams instance.`
+ );
+ } else if (
+ Env.BASE_URL &&
+ new URL(addon.manifestUrl).host === new URL(Env.BASE_URL).host &&
+ Env.DISABLE_SELF_SCRAPING === true
+ ) {
+ throw new Error(
+ `Scraping the same AIOStreams instance is disabled. Please use a different AIOStreams instance, or enable it through the environment variables.`
+ );
+ }
+ if (
+ addon.fromPresetId &&
+ FeatureControl.disabledAddons.has(addon.fromPresetId)
+ ) {
+ throw new Error(
+ `Addon ${addon.identifyingName} is disabled: ${FeatureControl.disabledAddons.get(
+ addon.fromPresetId
+ )}`
+ );
+ } else if (
+ FeatureControl.disabledHosts.has(new URL(addon.manifestUrl).host)
+ ) {
+ throw new Error(
+ `Addon ${addon.identifyingName} is disabled: ${FeatureControl.disabledHosts.get(
+ new URL(addon.manifestUrl).host
+ )}`
+ );
+ }
+ }
+
+ private async applyFilters(
+ streams: ParsedStream[],
+ type: string,
+ id: string
+ ): Promise {
+ interface SkipReason {
+ total: number;
+ details: Record;
+ }
+ const skipReasons: Record = {
+ titleMatching: { total: 0, details: {} },
+ seasonEpisodeMatching: { total: 0, details: {} },
+ excludedStreamType: { total: 0, details: {} },
+ requiredStreamType: { total: 0, details: {} },
+ excludedResolution: { total: 0, details: {} },
+ requiredResolution: { total: 0, details: {} },
+ excludedQuality: { total: 0, details: {} },
+ requiredQuality: { total: 0, details: {} },
+ excludedEncode: { total: 0, details: {} },
+ requiredEncode: { total: 0, details: {} },
+ excludedVisualTag: { total: 0, details: {} },
+ requiredVisualTag: { total: 0, details: {} },
+ excludedAudioTag: { total: 0, details: {} },
+ requiredAudioTag: { total: 0, details: {} },
+ excludedLanguage: { total: 0, details: {} },
+ requiredLanguage: { total: 0, details: {} },
+ excludedCached: { total: 0, details: {} },
+ requiredCached: { total: 0, details: {} },
+ excludedUncached: { total: 0, details: {} },
+ requiredUncached: { total: 0, details: {} },
+ excludedRegex: { total: 0, details: {} },
+ requiredRegex: { total: 0, details: {} },
+ excludedKeywords: { total: 0, details: {} },
+ requiredKeywords: { total: 0, details: {} },
+ requiredSeeders: { total: 0, details: {} },
+ excludedSeeders: { total: 0, details: {} },
+ size: { total: 0, details: {} },
+ };
+
+ const start = Date.now();
+ const isRegexAllowed = FeatureControl.isRegexAllowed(this.userData);
+
+ let titles: string[] = [];
+ if (this.userData.titleMatching && TYPES.includes(type as any)) {
+ try {
+ titles = await new TMDBMetadata(
+ this.userData.tmdbAccessToken
+ ).getTitles(id, type as any);
+ logger.info(`Found ${titles.length} titles for ${id}`, { titles });
+ } catch (error) {
+ logger.error(`Error fetching titles for ${id}: ${error}`);
+ }
+ }
+
+ const normaliseTitle = (title: string) => {
+ return title
+ .replace(/[^\p{L}\p{N}+]/gu, '')
+ .replace(/\s+/g, '')
+ .toLowerCase();
+ };
+
+ const performTitleMatch = (stream: ParsedStream) => {
+ const titleMatchingOptions = this.userData.titleMatching;
+ if (!titleMatchingOptions || !titleMatchingOptions.enabled) {
+ return true;
+ }
+ if (titles.length === 0) {
+ // don't filter out streams if no titles could be found
+ return true;
+ }
+ const streamTitle = stream.parsedFile?.title;
+ if (!streamTitle) {
+ // if a specific stream doesn't have a title, filter it out.
+ return false;
+ }
+
+ // now check if we need to check this stream based on the addon and request type
+ if (
+ titleMatchingOptions.requestTypes?.length &&
+ !titleMatchingOptions.requestTypes.includes(type)
+ ) {
+ return true;
+ }
+ if (
+ titleMatchingOptions.addons?.length &&
+ !titleMatchingOptions.addons.includes(stream.addon.id!)
+ ) {
+ return true;
+ }
+
+ if (titleMatchingOptions.mode === 'exact') {
+ // the stream title should be an exact match of a valid title
+ return titles.some(
+ (title) => normaliseTitle(title) === normaliseTitle(streamTitle)
+ );
+ } else {
+ // a valid title should be present somewhere in the stream title
+ const valid = titles.some((title) =>
+ normaliseTitle(streamTitle).includes(normaliseTitle(title))
+ );
+ return valid;
+ }
+ };
+
+ const performSeasonEpisodeMatch = (stream: ParsedStream) => {
+ const seasonEpisodeMatchingOptions = this.userData.seasonEpisodeMatching;
+ if (
+ !seasonEpisodeMatchingOptions ||
+ !seasonEpisodeMatchingOptions.enabled
+ ) {
+ return true;
+ }
+
+ // parse the id to get the season and episode
+ const seasonEpisodeRegex = /:(\d+):(\d+)$/;
+ const match = id.match(seasonEpisodeRegex);
+
+ if (!match || !match[1] || !match[2]) {
+ // only if both season and episode are present, we can filter
+ return true;
+ }
+
+ const requestedSeason = parseInt(match[1]);
+ const requestedEpisode = parseInt(match[2]);
+
+ if (
+ seasonEpisodeMatchingOptions.requestTypes?.length &&
+ !seasonEpisodeMatchingOptions.requestTypes.includes(type)
+ ) {
+ return true;
+ }
+
+ if (
+ seasonEpisodeMatchingOptions.addons?.length &&
+ !seasonEpisodeMatchingOptions.addons.includes(stream.addon.id!)
+ ) {
+ return true;
+ }
+
+ // is requested season present
+ if (
+ requestedSeason &&
+ ((stream.parsedFile?.season &&
+ stream.parsedFile.season !== requestedSeason) ||
+ (stream.parsedFile?.seasons &&
+ !stream.parsedFile.seasons.includes(requestedSeason)))
+ ) {
+ return false;
+ }
+
+ // is requested episode present
+ if (
+ requestedEpisode &&
+ stream.parsedFile?.episode &&
+ stream.parsedFile.episode !== requestedEpisode
+ ) {
+ return false;
+ }
+
+ return true;
+ };
+
+ const excludedRegexPatterns =
+ isRegexAllowed && this.userData.excludedRegexPatterns
+ ? await Promise.all(
+ this.userData.excludedRegexPatterns.map(
+ async (pattern) => await compileRegex(pattern)
+ )
+ )
+ : undefined;
+
+ const requiredRegexPatterns =
+ isRegexAllowed && this.userData.requiredRegexPatterns
+ ? await Promise.all(
+ this.userData.requiredRegexPatterns.map(
+ async (pattern) => await compileRegex(pattern)
+ )
+ )
+ : undefined;
+
+ const includedRegexPatterns =
+ isRegexAllowed && this.userData.includedRegexPatterns
+ ? await Promise.all(
+ this.userData.includedRegexPatterns.map(
+ async (pattern) => await compileRegex(pattern)
+ )
+ )
+ : undefined;
+
+ const excludedKeywordsPattern = this.userData.excludedKeywords
+ ? await formRegexFromKeywords(this.userData.excludedKeywords)
+ : undefined;
+
+ const requiredKeywordsPattern = this.userData.requiredKeywords
+ ? await formRegexFromKeywords(this.userData.requiredKeywords)
+ : undefined;
+
+ const includedKeywordsPattern = this.userData.includedKeywords
+ ? await formRegexFromKeywords(this.userData.includedKeywords)
+ : undefined;
+
+ // test many regexes against many attributes and return true if at least one regex matches any attribute
+ // and false if no regex matches any attribute
+ const testRegexes = async (stream: ParsedStream, patterns: RegExp[]) => {
+ const file = stream.parsedFile;
+ const stringsToTest = [
+ stream.filename,
+ file?.releaseGroup,
+ stream.indexer,
+ stream.folderName,
+ ].filter((v) => v !== undefined);
+
+ for (const string of stringsToTest) {
+ for (const pattern of patterns) {
+ if (await safeRegexTest(pattern, string)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ const filterBasedOnCacheStatus = (
+ stream: ParsedStream,
+ mode: 'and' | 'or',
+ addonIds: string[] | undefined,
+ serviceIds: string[] | undefined,
+ streamTypes: StreamType[] | undefined,
+ cached: boolean
+ ) => {
+ const isAddonFilteredOut =
+ addonIds &&
+ addonIds.length > 0 &&
+ addonIds.some((addonId) => stream.addon.id === addonId) &&
+ stream.service?.cached === cached;
+ const isServiceFilteredOut =
+ serviceIds &&
+ serviceIds.length > 0 &&
+ serviceIds.some((serviceId) => stream.service?.id === serviceId) &&
+ stream.service?.cached === cached;
+ const isStreamTypeFilteredOut =
+ streamTypes &&
+ streamTypes.length > 0 &&
+ streamTypes.includes(stream.type) &&
+ stream.service?.cached === cached;
+
+ if (mode === 'and') {
+ return !(
+ isAddonFilteredOut &&
+ isServiceFilteredOut &&
+ isStreamTypeFilteredOut
+ );
+ } else {
+ return !(
+ isAddonFilteredOut ||
+ isServiceFilteredOut ||
+ isStreamTypeFilteredOut
+ );
+ }
+ };
+
+ const normaliseRange = (
+ range: [number, number] | undefined,
+ defaults: { min: number; max: number }
+ ): [number | undefined, number | undefined] | undefined => {
+ if (!range) return undefined;
+ const [min, max] = range;
+ const normMin = min === defaults.min ? undefined : min;
+ const normMax = max === defaults.max ? undefined : max;
+ return normMin === undefined && normMax === undefined
+ ? undefined
+ : [normMin, normMax];
+ };
+
+ const normaliseSeederRange = (
+ seederRange: [number, number] | undefined
+ ) => {
+ return normaliseRange(seederRange, {
+ min: constants.MIN_SEEDERS,
+ max: constants.MAX_SEEDERS,
+ });
+ };
+
+ const normaliseSizeRange = (sizeRange: [number, number] | undefined) => {
+ return normaliseRange(sizeRange, {
+ min: constants.MIN_SIZE,
+ max: constants.MAX_SIZE,
+ });
+ };
+
+ const getStreamType = (
+ stream: ParsedStream
+ ): 'p2p' | 'cached' | 'uncached' | undefined => {
+ switch (stream.type) {
+ case 'debrid':
+ return stream.service?.cached ? 'cached' : 'uncached';
+ case 'usenet':
+ return stream.service?.cached ? 'cached' : 'uncached';
+ case 'p2p':
+ return 'p2p';
+ default:
+ return undefined;
+ }
+ };
+
+ const shouldKeepStream = async (stream: ParsedStream): Promise => {
+ const file = stream.parsedFile;
+
+ // carry out include checks first
+ if (this.userData.includedStreamTypes?.includes(stream.type)) {
+ return true;
+ }
+
+ if (
+ this.userData.includedResolutions?.includes(
+ file?.resolution || ('Unknown' as any)
+ )
+ ) {
+ return true;
+ }
+
+ if (
+ this.userData.includedQualities?.includes(
+ file?.quality || ('Unknown' as any)
+ )
+ ) {
+ return true;
+ }
+
+ if (
+ this.userData.includedVisualTags?.some((tag) =>
+ (file?.visualTags.length ? file.visualTags : ['Unknown']).includes(
+ tag
+ )
+ )
+ ) {
+ return true;
+ }
+
+ if (
+ this.userData.includedAudioTags?.some((tag) =>
+ (file?.audioTags.length ? file.audioTags : ['Unknown']).includes(tag)
+ )
+ ) {
+ return true;
+ }
+
+ if (
+ this.userData.includedAudioChannels?.some((channel) =>
+ (file?.audioChannels.length
+ ? file.audioChannels
+ : ['Unknown']
+ ).includes(channel)
+ )
+ ) {
+ return true;
+ }
+
+ if (
+ this.userData.includedLanguages?.some((lang) =>
+ (file?.languages.length ? file.languages : ['Unknown']).includes(lang)
+ )
+ ) {
+ return true;
+ }
+
+ if (
+ this.userData.includedEncodes?.some(
+ (encode) => (file?.encode || 'Unknown') === encode
+ )
+ ) {
+ return true;
+ }
+
+ if (
+ includedRegexPatterns &&
+ (await testRegexes(stream, includedRegexPatterns))
+ ) {
+ return true;
+ }
+
+ if (
+ includedKeywordsPattern &&
+ (await testRegexes(stream, [includedKeywordsPattern]))
+ ) {
+ return true;
+ }
+
+ const includedSeederRange = normaliseSeederRange(
+ this.userData.includeSeederRange
+ );
+ const excludedSeederRange = normaliseSeederRange(
+ this.userData.excludeSeederRange
+ );
+ const requiredSeederRange = normaliseSeederRange(
+ this.userData.requiredSeederRange
+ );
+
+ const typeForSeederRange = getStreamType(stream);
+
+ if (
+ includedSeederRange &&
+ (!this.userData.seederRangeTypes ||
+ (typeForSeederRange &&
+ this.userData.seederRangeTypes.includes(typeForSeederRange)))
+ ) {
+ if (
+ stream.torrent?.seeders &&
+ includedSeederRange[0] &&
+ stream.torrent.seeders > includedSeederRange[0]
+ ) {
+ return true;
+ }
+ if (
+ stream.torrent?.seeders &&
+ includedSeederRange[1] &&
+ stream.torrent.seeders < includedSeederRange[1]
+ ) {
+ return true;
+ }
+ }
+
+ if (this.userData.excludedStreamTypes?.includes(stream.type)) {
+ // Track stream type exclusions
+ skipReasons.excludedStreamType.total++;
+ skipReasons.excludedStreamType.details[stream.type] =
+ (skipReasons.excludedStreamType.details[stream.type] || 0) + 1;
+ return false;
+ }
+
+ // Track required stream type misses
+ if (
+ this.userData.requiredStreamTypes &&
+ this.userData.requiredStreamTypes.length > 0 &&
+ !this.userData.requiredStreamTypes.includes(stream.type)
+ ) {
+ skipReasons.requiredStreamType.total++;
+ skipReasons.requiredStreamType.details[stream.type] =
+ (skipReasons.requiredStreamType.details[stream.type] || 0) + 1;
+ return false;
+ }
+
+ // Resolutions
+ if (
+ this.userData.excludedResolutions?.includes(
+ (file?.resolution || 'Unknown') as any
+ )
+ ) {
+ skipReasons.excludedResolution.total++;
+ skipReasons.excludedResolution.details[file?.resolution || 'Unknown'] =
+ (skipReasons.excludedResolution.details[
+ file?.resolution || 'Unknown'
+ ] || 0) + 1;
+ return false;
+ }
+
+ if (
+ this.userData.requiredResolutions &&
+ this.userData.requiredResolutions.length > 0 &&
+ !this.userData.requiredResolutions.includes(
+ (file?.resolution || 'Unknown') as any
+ )
+ ) {
+ skipReasons.requiredResolution.total++;
+ skipReasons.requiredResolution.details[file?.resolution || 'Unknown'] =
+ (skipReasons.requiredResolution.details[
+ file?.resolution || 'Unknown'
+ ] || 0) + 1;
+ return false;
+ }
+
+ // Qualities
+ if (
+ this.userData.excludedQualities?.includes(
+ (file?.quality || 'Unknown') as any
+ )
+ ) {
+ skipReasons.excludedQuality.total++;
+ skipReasons.excludedQuality.details[file?.quality || 'Unknown'] =
+ (skipReasons.excludedQuality.details[file?.quality || 'Unknown'] ||
+ 0) + 1;
+ return false;
+ }
+
+ if (
+ this.userData.requiredQualities &&
+ this.userData.requiredQualities.length > 0 &&
+ !this.userData.requiredQualities.includes(
+ (file?.quality || 'Unknown') as any
+ )
+ ) {
+ skipReasons.requiredQuality.total++;
+ skipReasons.requiredQuality.details[file?.quality || 'Unknown'] =
+ (skipReasons.requiredQuality.details[file?.quality || 'Unknown'] ||
+ 0) + 1;
+ return false;
+ }
+
+ // encode
+ if (
+ this.userData.excludedEncodes?.includes(
+ file?.encode || ('Unknown' as any)
+ )
+ ) {
+ skipReasons.excludedEncode.total++;
+ skipReasons.excludedEncode.details[file?.encode || 'Unknown'] =
+ (skipReasons.excludedEncode.details[file?.encode || 'Unknown'] || 0) +
+ 1;
+ return false;
+ }
+
+ if (
+ this.userData.requiredEncodes &&
+ this.userData.requiredEncodes.length > 0 &&
+ !this.userData.requiredEncodes.includes(
+ file?.encode || ('Unknown' as any)
+ )
+ ) {
+ skipReasons.requiredEncode.total++;
+ skipReasons.requiredEncode.details[file?.encode || 'Unknown'] =
+ (skipReasons.requiredEncode.details[file?.encode || 'Unknown'] || 0) +
+ 1;
+ return false;
+ }
+
+ // temporarily add HDR+DV to visual tags list if both HDR and DV are present
+ // to allow HDR+DV option in userData to work
+ if (
+ file?.visualTags?.some((tag) => tag.startsWith('HDR')) &&
+ file?.visualTags?.some((tag) => tag.startsWith('DV'))
+ ) {
+ const hdrIndex = file?.visualTags?.findIndex((tag) =>
+ tag.startsWith('HDR')
+ );
+ const dvIndex = file?.visualTags?.findIndex((tag) =>
+ tag.startsWith('DV')
+ );
+ const insertIndex = Math.min(hdrIndex, dvIndex);
+ file?.visualTags?.splice(insertIndex, 0, 'HDR+DV');
+ }
+
+ if (
+ this.userData.excludedVisualTags?.some((tag) =>
+ (file?.visualTags.length ? file.visualTags : ['Unknown']).includes(
+ tag
+ )
+ )
+ ) {
+ const tag = this.userData.excludedVisualTags.find((tag) =>
+ (file?.visualTags.length ? file.visualTags : ['Unknown']).includes(
+ tag
+ )
+ );
+ skipReasons.excludedVisualTag.total++;
+ skipReasons.excludedVisualTag.details[tag!] =
+ (skipReasons.excludedVisualTag.details[tag!] || 0) + 1;
+ return false;
+ }
+
+ if (
+ this.userData.requiredVisualTags &&
+ this.userData.requiredVisualTags.length > 0 &&
+ !this.userData.requiredVisualTags.some((tag) =>
+ (file?.visualTags.length ? file.visualTags : ['Unknown']).includes(
+ tag
+ )
+ )
+ ) {
+ const tag = this.userData.requiredVisualTags.find((tag) =>
+ (file?.visualTags.length ? file.visualTags : ['Unknown']).includes(
+ tag
+ )
+ );
+ skipReasons.requiredVisualTag.total++;
+ skipReasons.requiredVisualTag.details[tag!] =
+ (skipReasons.requiredVisualTag.details[tag!] || 0) + 1;
+ return false;
+ }
+
+ if (
+ this.userData.excludedAudioTags?.some((tag) =>
+ (file?.audioTags.length ? file.audioTags : ['Unknown']).includes(tag)
+ )
+ ) {
+ const tag = this.userData.excludedAudioTags.find((tag) =>
+ (file?.audioTags.length ? file.audioTags : ['Unknown']).includes(tag)
+ );
+ skipReasons.excludedAudioTag.total++;
+ skipReasons.excludedAudioTag.details[tag!] =
+ (skipReasons.excludedAudioTag.details[tag!] || 0) + 1;
+ return false;
+ }
+
+ if (
+ this.userData.requiredAudioTags &&
+ this.userData.requiredAudioTags.length > 0 &&
+ !this.userData.requiredAudioTags.some((tag) =>
+ (file?.audioTags.length ? file.audioTags : ['Unknown']).includes(tag)
+ )
+ ) {
+ const tag = this.userData.requiredAudioTags.find((tag) =>
+ (file?.audioTags.length ? file.audioTags : ['Unknown']).includes(tag)
+ );
+ skipReasons.requiredAudioTag.total++;
+ skipReasons.requiredAudioTag.details[tag!] =
+ (skipReasons.requiredAudioTag.details[tag!] || 0) + 1;
+ return false;
+ }
+
+ if (
+ this.userData.excludedAudioChannels?.some((channel) =>
+ (file?.audioChannels.length
+ ? file.audioChannels
+ : ['Unknown']
+ ).includes(channel)
+ )
+ ) {
+ const channel = this.userData.excludedAudioChannels.find((channel) =>
+ (file?.audioChannels.length
+ ? file.audioChannels
+ : ['Unknown']
+ ).includes(channel)
+ );
+ skipReasons.excludedAudioChannel.total++;
+ skipReasons.excludedAudioChannel.details[channel!] =
+ (skipReasons.excludedAudioChannel.details[channel!] || 0) + 1;
+ return false;
+ }
+
+ if (
+ this.userData.requiredAudioChannels &&
+ this.userData.requiredAudioChannels.length > 0 &&
+ !this.userData.requiredAudioChannels.some((channel) =>
+ (file?.audioChannels.length
+ ? file.audioChannels
+ : ['Unknown']
+ ).includes(channel)
+ )
+ ) {
+ const channel = this.userData.requiredAudioChannels.find((channel) =>
+ (file?.audioChannels.length
+ ? file.audioChannels
+ : ['Unknown']
+ ).includes(channel)
+ );
+ skipReasons.requiredAudioChannel.total++;
+ skipReasons.requiredAudioChannel.details[channel!] =
+ (skipReasons.requiredAudioChannel.details[channel!] || 0) + 1;
+ return false;
+ }
+
+ // languages
+ if (
+ this.userData.excludedLanguages?.some((lang) =>
+ (file?.languages.length ? file.languages : ['Unknown']).includes(lang)
+ )
+ ) {
+ const lang = this.userData.excludedLanguages.find((lang) =>
+ (file?.languages.length ? file.languages : ['Unknown']).includes(lang)
+ );
+ skipReasons.excludedLanguage.total++;
+ skipReasons.excludedLanguage.details[lang!] =
+ (skipReasons.excludedLanguage.details[lang!] || 0) + 1;
+ return false;
+ }
+
+ if (
+ this.userData.requiredLanguages &&
+ this.userData.requiredLanguages.length > 0 &&
+ !this.userData.requiredLanguages.some((lang) =>
+ (file?.languages.length ? file.languages : ['Unknown']).includes(lang)
+ )
+ ) {
+ const lang = this.userData.requiredLanguages.find((lang) =>
+ (file?.languages.length ? file.languages : ['Unknown']).includes(lang)
+ );
+ skipReasons.requiredLanguage.total++;
+ skipReasons.requiredLanguage.details[lang!] =
+ (skipReasons.requiredLanguage.details[lang!] || 0) + 1;
+ return false;
+ }
+
+ // uncached
+
+ if (this.userData.excludeUncached && stream.service?.cached === false) {
+ skipReasons.excludedUncached.total++;
+ return false;
+ }
+
+ if (this.userData.excludeCached && stream.service?.cached === true) {
+ skipReasons.excludedCached.total++;
+ return false;
+ }
+
+ if (
+ filterBasedOnCacheStatus(
+ stream,
+ this.userData.excludeCachedMode || 'or',
+ this.userData.excludeCachedFromAddons,
+ this.userData.excludeCachedFromServices,
+ this.userData.excludeCachedFromStreamTypes,
+ true
+ ) === false
+ ) {
+ skipReasons.excludedCached.total++;
+ return false;
+ }
+
+ if (
+ filterBasedOnCacheStatus(
+ stream,
+ this.userData.excludeUncachedMode || 'or',
+ this.userData.excludeUncachedFromAddons,
+ this.userData.excludeUncachedFromServices,
+ this.userData.excludeUncachedFromStreamTypes,
+ false
+ ) === false
+ ) {
+ skipReasons.excludedUncached.total++;
+ return false;
+ }
+
+ if (
+ excludedRegexPatterns &&
+ (await testRegexes(stream, excludedRegexPatterns))
+ ) {
+ skipReasons.excludedRegex.total++;
+ return false;
+ }
+ if (
+ requiredRegexPatterns &&
+ !(await testRegexes(stream, requiredRegexPatterns))
+ ) {
+ skipReasons.requiredRegex.total++;
+ return false;
+ }
+
+ if (
+ excludedKeywordsPattern &&
+ (await testRegexes(stream, [excludedKeywordsPattern]))
+ ) {
+ skipReasons.excludedKeywords.total++;
+ return false;
+ }
+
+ if (
+ requiredKeywordsPattern &&
+ !(await testRegexes(stream, [requiredKeywordsPattern]))
+ ) {
+ skipReasons.requiredKeywords.total++;
+ return false;
+ }
+
+ if (
+ requiredSeederRange &&
+ (!this.userData.seederRangeTypes ||
+ (typeForSeederRange &&
+ this.userData.seederRangeTypes.includes(typeForSeederRange)))
+ ) {
+ if (
+ stream.torrent?.seeders &&
+ requiredSeederRange[0] &&
+ stream.torrent.seeders < requiredSeederRange[0]
+ ) {
+ return false;
+ }
+ if (
+ stream.torrent?.seeders &&
+ requiredSeederRange[1] &&
+ stream.torrent.seeders > requiredSeederRange[1]
+ ) {
+ return false;
+ }
+ }
+
+ if (
+ excludedSeederRange &&
+ (!this.userData.seederRangeTypes ||
+ (typeForSeederRange &&
+ this.userData.seederRangeTypes.includes(typeForSeederRange)))
+ ) {
+ if (
+ stream.torrent?.seeders &&
+ excludedSeederRange[0] &&
+ stream.torrent.seeders > excludedSeederRange[0]
+ ) {
+ return false;
+ }
+ if (
+ stream.torrent?.seeders &&
+ excludedSeederRange[1] &&
+ stream.torrent.seeders < excludedSeederRange[1]
+ ) {
+ return false;
+ }
+ }
+
+ if (!performTitleMatch(stream)) {
+ skipReasons.titleMatching.total++;
+ skipReasons.titleMatching.details[
+ stream.parsedFile?.title || 'Unknown'
+ ] =
+ (skipReasons.titleMatching.details[
+ stream.parsedFile?.title || 'Unknown'
+ ] || 0) + 1;
+ return false;
+ }
+
+ if (!performSeasonEpisodeMatch(stream)) {
+ const detail =
+ stream.parsedFile?.title +
+ ' ' +
+ (stream.parsedFile?.seasonEpisode?.join(' x ') || 'Unknown');
+
+ skipReasons.seasonEpisodeMatching.total++;
+ skipReasons.seasonEpisodeMatching.details[detail] =
+ (skipReasons.seasonEpisodeMatching.details[detail] || 0) + 1;
+ return false;
+ }
+
+ const global = this.userData.size?.global;
+ const resolution = stream.parsedFile?.resolution
+ ? this.userData.size?.resolution?.[
+ stream.parsedFile
+ .resolution as keyof typeof this.userData.size.resolution
+ ]
+ : undefined;
+
+ let minMax: [number | undefined, number | undefined] | undefined;
+ if (type === 'movie') {
+ minMax =
+ normaliseSizeRange(resolution?.movies) ||
+ normaliseSizeRange(global?.movies);
+ } else {
+ minMax =
+ normaliseSizeRange(resolution?.series) ||
+ normaliseSizeRange(global?.series);
+ }
+
+ if (minMax) {
+ if (stream.size && minMax[0] && stream.size < minMax[0]) {
+ skipReasons.size.total++;
+ return false;
+ }
+ if (stream.size && minMax[1] && stream.size > minMax[1]) {
+ skipReasons.size.total++;
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+ const filterResults = await Promise.all(streams.map(shouldKeepStream));
+ const filteredStreams = streams.filter((_, index) => filterResults[index]);
+
+ // Log filter summary
+ const totalFiltered = streams.length - filteredStreams.length;
+ if (totalFiltered > 0) {
+ const summary = [
+ '\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
+ ` 🔍 Filter Summary`,
+ '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━',
+ ` 📊 Total Streams : ${streams.length}`,
+ ` ✔️ Kept : ${filteredStreams.length}`,
+ ` ❌ Filtered : ${totalFiltered}`,
+ ];
+
+ // Add filter details if any streams were filtered
+ const filterDetails: string[] = [];
+ for (const [reason, stats] of Object.entries(skipReasons)) {
+ if (stats.total > 0) {
+ // Convert camelCase to Title Case with spaces
+ const formattedReason = reason
+ .replace(/([A-Z])/g, ' $1')
+ .replace(/^./, (str) => str.toUpperCase());
+
+ filterDetails.push(`\n 📌 ${formattedReason} (${stats.total})`);
+ for (const [detail, count] of Object.entries(stats.details)) {
+ filterDetails.push(` • ${count}× ${detail}`);
+ }
+ }
+ }
+
+ if (filterDetails.length > 0) {
+ summary.push('\n 🔎 Filter Details:');
+ summary.push(...filterDetails);
+ }
+
+ summary.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
+ logger.info(summary.join('\n'));
+ }
+
+ logger.info(`Applied filters in ${getTimeTakenSincePoint(start)}`);
+ return filteredStreams;
+ }
+
+ private deduplicateStreams(streams: ParsedStream[]): ParsedStream[] {
+ let deduplicator = this.userData.deduplicator;
+ if (!deduplicator || !deduplicator.enabled) {
+ return streams;
+ }
+ const start = Date.now();
+
+ const deduplicationKeys = deduplicator.keys || ['filename', 'infoHash'];
+
+ deduplicator = {
+ enabled: true,
+ keys: deduplicationKeys,
+ cached: deduplicator.cached || 'per_addon',
+ uncached: deduplicator.uncached || 'per_addon',
+ p2p: deduplicator.p2p || 'per_addon',
+ http: deduplicator.http || 'disabled',
+ live: deduplicator.live || 'disabled',
+ youtube: deduplicator.youtube || 'disabled',
+ external: deduplicator.external || 'disabled',
+ };
+
+ // Group streams by their deduplication keys
+ const streamGroups = new Map();
+
+ for (const stream of streams) {
+ // Create a unique key based on the selected deduplication methods
+ const keys: string[] = [];
+
+ if (deduplicationKeys.includes('filename') && stream.filename) {
+ let normalisedFilename = stream.filename
+ .replace(
+ /(mkv|mp4|avi|mov|wmv|flv|webm|m4v|mpg|mpeg|3gp|3g2|m2ts|ts|vob|ogv|ogm|divx|xvid|rm|rmvb|asf|mxf|mka|mks|mk3d|webm|f4v|f4p|f4a|f4b)$/i,
+ ''
+ )
+ .replace(/[^\p{L}\p{N}+]/gu, '')
+ .replace(/\s+/g, '')
+ .toLowerCase();
+ keys.push(`filename:${normalisedFilename}`);
+ }
+
+ if (deduplicationKeys.includes('infoHash') && stream.torrent?.infoHash) {
+ keys.push(`infoHash:${stream.torrent.infoHash}`);
+ }
+
+ if (deduplicationKeys.includes('smartDetect')) {
+ // generate a hash using many different attributes
+ // round size to nearest 100MB for some margin of error
+ const roundedSize = stream.size
+ ? Math.round(stream.size / 100000000) * 100000000
+ : undefined;
+ const hash = getSimpleTextHash(
+ `${roundedSize}${stream.parsedFile?.resolution}${stream.parsedFile?.quality}${stream.parsedFile?.visualTags}${stream.parsedFile?.audioTags}${stream.parsedFile?.languages}${stream.parsedFile?.encode}`
+ );
+ keys.push(`smartDetect:${hash}`);
+ }
+
+ // If no keys match, keep the stream
+ if (keys.length === 0) {
+ streamGroups.set(`unique_${Math.random()}`, [stream]);
+ continue;
+ }
+
+ // Add stream to all matching key groups
+ for (const key of keys) {
+ const group = streamGroups.get(key) || [];
+ group.push(stream);
+ streamGroups.set(key, group);
+ }
+ }
+
+ // Process each group based on stream types and deduplication modes
+ const processedStreams = new Set();
+
+ for (const group of streamGroups.values()) {
+ // Group streams by type
+ const streamsByType = new Map();
+ for (const stream of group) {
+ let type = stream.type as string;
+ if ((type === 'debrid' || type === 'usenet') && stream.service) {
+ type = stream.service.cached ? 'cached' : 'uncached';
+ }
+ const typeGroup = streamsByType.get(type) || [];
+ typeGroup.push(stream);
+ streamsByType.set(type, typeGroup);
+ }
+
+ // Process each type according to its deduplication mode
+ for (const [type, typeStreams] of streamsByType.entries()) {
+ const mode = deduplicator[type as keyof typeof deduplicator] as string;
+ if (mode === 'disabled') {
+ typeStreams.forEach((stream) => processedStreams.add(stream));
+ continue;
+ }
+
+ switch (mode) {
+ case 'single_result': {
+ // Keep one result with highest priority service and addon
+ let selectedStream = typeStreams.sort((a, b) => {
+ // so a specific type may either have both streams not have a service, or both streams have a service
+ // if both streams have a service, then we can simpl
+ const aProviderIndex =
+ this.userData.services?.findIndex(
+ (service) => service.id === a.service?.id
+ ) ?? -1;
+ const bProviderIndex =
+ this.userData.services?.findIndex(
+ (service) => service.id === b.service?.id
+ ) ?? -1;
+
+ if (
+ aProviderIndex &&
+ bProviderIndex &&
+ aProviderIndex !== bProviderIndex
+ ) {
+ return aProviderIndex - bProviderIndex;
+ }
+
+ // look at seeders for p2p and uncached streams
+ if (
+ (type === 'p2p' || type === 'uncached') &&
+ a.torrent?.seeders &&
+ b.torrent?.seeders
+ ) {
+ return (b.torrent.seeders || 0) - (a.torrent.seeders || 0);
+ }
+
+ // now look at the addon index
+
+ const aAddonIndex =
+ this.userData.presets.findIndex(
+ (preset) => JSON.stringify(preset) === a.addon.id
+ ) ?? -1;
+ const bAddonIndex =
+ this.userData.presets.findIndex(
+ (preset) => JSON.stringify(preset) === b.addon.id
+ ) ?? -1;
+
+ // the addon index MUST exist, its not possible for it to not exist
+ if (aAddonIndex !== bAddonIndex) {
+ return aAddonIndex - bAddonIndex;
+ }
+
+ // now look at stream type
+ const aTypeIndex =
+ this.userData.preferredStreamTypes?.findIndex(
+ (type) => type === a.type
+ ) ?? 0;
+ const bTypeIndex =
+ this.userData.preferredStreamTypes?.findIndex(
+ (type) => type === b.type
+ ) ?? 0;
+
+ if (aTypeIndex !== bTypeIndex) {
+ return aTypeIndex - bTypeIndex;
+ }
+
+ return 0;
+ })[0];
+ processedStreams.add(selectedStream);
+ break;
+ }
+ case 'per_service': {
+ // Keep one result from each service (highest priority available addon for that service)
+ // first, ensure that all streams have a service, otherwise we can't use this mode
+ if (typeStreams.some((stream) => !stream.service)) {
+ throw new Error(
+ 'per_service mode requires all streams to have a service'
+ );
+ }
+ let perServiceStreams = Object.values(
+ typeStreams.reduce(
+ (acc, stream) => {
+ acc[stream.service!.id] = acc[stream.service!.id] || [];
+ acc[stream.service!.id].push(stream);
+ return acc;
+ },
+ {} as Record
+ )
+ ).map((serviceStreams) => {
+ return serviceStreams.sort((a, b) => {
+ const aAddonIndex =
+ this.userData.presets.findIndex(
+ (preset) => JSON.stringify(preset) === a.addon.id
+ ) ?? -1;
+ const bAddonIndex =
+ this.userData.presets.findIndex(
+ (preset) => JSON.stringify(preset) === b.addon.id
+ ) ?? -1;
+ if (aAddonIndex !== bAddonIndex) {
+ return aAddonIndex - bAddonIndex;
+ }
+
+ // now look at stream type
+ const aTypeIndex =
+ this.userData.preferredStreamTypes?.findIndex(
+ (type) => type === a.type
+ ) ?? 0;
+ const bTypeIndex =
+ this.userData.preferredStreamTypes?.findIndex(
+ (type) => type === b.type
+ ) ?? 0;
+ if (aTypeIndex !== bTypeIndex) {
+ return aTypeIndex - bTypeIndex;
+ }
+
+ // look at seeders for p2p and uncached streams
+ if (type === 'p2p' || type === 'uncached') {
+ return (b.torrent?.seeders || 0) - (a.torrent?.seeders || 0);
+ }
+ return 0;
+ })[0];
+ });
+ for (const stream of perServiceStreams) {
+ processedStreams.add(stream);
+ }
+ break;
+ }
+ case 'per_addon': {
+ if (typeStreams.some((stream) => !stream.addon)) {
+ throw new Error(
+ 'per_addon mode requires all streams to have an addon'
+ );
+ }
+ let perAddonStreams = Object.values(
+ typeStreams.reduce(
+ (acc, stream) => {
+ acc[stream.addon.id!] = acc[stream.addon.id!] || [];
+ acc[stream.addon.id!].push(stream);
+ return acc;
+ },
+ {} as Record
+ )
+ ).map((addonStreams) => {
+ return addonStreams.sort((a, b) => {
+ const aServiceIndex =
+ this.userData.services?.findIndex(
+ (service) => service.id === a.service?.id
+ ) ?? -1;
+ const bServiceIndex =
+ this.userData.services?.findIndex(
+ (service) => service.id === b.service?.id
+ ) ?? -1;
+ if (aServiceIndex !== bServiceIndex) {
+ return aServiceIndex - bServiceIndex;
+ }
+
+ // look at seeders for p2p and uncached streams
+ if (type === 'p2p' || type === 'uncached') {
+ return (b.torrent?.seeders || 0) - (a.torrent?.seeders || 0);
+ }
+ return 0;
+ })[0];
+ });
+ for (const stream of perAddonStreams) {
+ processedStreams.add(stream);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ let deduplicatedStreams = Array.from(processedStreams);
+ logger.info(
+ `Filtered out ${streams.length - deduplicatedStreams.length} duplicate streams to ${deduplicatedStreams.length} streams in ${getTimeTakenSincePoint(start)}`
+ );
+ return deduplicatedStreams;
+ }
+
+ private async precomputeSortRegexes(streams: ParsedStream[]) {
+ const preferredRegexPatterns =
+ FeatureControl.isRegexAllowed(this.userData) &&
+ this.userData.preferredRegexPatterns
+ ? await Promise.all(
+ this.userData.preferredRegexPatterns.map(async (pattern) => {
+ return {
+ name: pattern.name,
+ pattern: await compileRegex(pattern.pattern),
+ };
+ })
+ )
+ : undefined;
+ const preferredKeywordsPatterns = this.userData.preferredKeywords
+ ? await formRegexFromKeywords(this.userData.preferredKeywords)
+ : undefined;
+ if (!preferredRegexPatterns && !preferredKeywordsPatterns) {
+ return;
+ }
+ const start = Date.now();
+ if (preferredKeywordsPatterns) {
+ streams.forEach((stream) => {
+ stream.keywordMatched =
+ isMatch(preferredKeywordsPatterns, stream.filename || '') ||
+ isMatch(preferredKeywordsPatterns, stream.folderName || '') ||
+ isMatch(
+ preferredKeywordsPatterns,
+ stream.parsedFile?.releaseGroup || ''
+ ) ||
+ isMatch(preferredKeywordsPatterns, stream.indexer || '');
+ });
+ }
+ if (preferredRegexPatterns) {
+ streams.forEach((stream) => {
+ for (let i = 0; i < preferredRegexPatterns.length; i++) {
+ const regexPattern = preferredRegexPatterns[i];
+ if (
+ regexPattern &&
+ !stream.regexMatched &&
+ ((stream.filename &&
+ isMatch(regexPattern.pattern, stream.filename)) ||
+ (stream.folderName &&
+ isMatch(regexPattern.pattern, stream.folderName)) ||
+ (stream.parsedFile?.releaseGroup &&
+ isMatch(
+ regexPattern.pattern,
+ stream.parsedFile?.releaseGroup || ''
+ )) ||
+ (stream.indexer && isMatch(regexPattern.pattern, stream.indexer)))
+ ) {
+ stream.regexMatched = {
+ name: regexPattern.name,
+ pattern: regexPattern.pattern.source,
+ index: i,
+ };
+ break;
+ }
+ }
+ });
+ }
+ logger.info(`Precomputed sort regexes in ${getTimeTakenSincePoint(start)}`);
+ }
+
+ private sortStreams(streams: ParsedStream[], type: string): ParsedStream[] {
+ let sortCriteria = this.userData.sortCriteria.global;
+ let cachedSortCriteria = this.userData.sortCriteria.cached;
+ let uncachedSortCriteria = this.userData.sortCriteria.uncached;
+
+ const start = Date.now();
+
+ if (type === 'movie' && this.userData.sortCriteria?.movies?.length) {
+ logger.info('Using movie sort criteria');
+ sortCriteria = this.userData.sortCriteria?.movies;
+ if (this.userData.sortCriteria?.cachedMovies?.length) {
+ cachedSortCriteria = this.userData.sortCriteria?.cachedMovies;
+ }
+ if (this.userData.sortCriteria?.uncachedMovies?.length) {
+ uncachedSortCriteria = this.userData.sortCriteria?.uncachedMovies;
+ }
+ }
+
+ if (type === 'series' && this.userData.sortCriteria?.series?.length) {
+ logger.info('Using series sort criteria');
+ sortCriteria = this.userData.sortCriteria?.series;
+ if (this.userData.sortCriteria?.cachedSeries?.length) {
+ cachedSortCriteria = this.userData.sortCriteria?.cachedSeries;
+ }
+ if (this.userData.sortCriteria?.uncachedSeries?.length) {
+ uncachedSortCriteria = this.userData.sortCriteria?.uncachedSeries;
+ }
+ }
+ let sortedStreams = [];
+
+ if (
+ cachedSortCriteria?.length &&
+ uncachedSortCriteria?.length &&
+ sortCriteria.length > 0 &&
+ sortCriteria[0].key === 'cached'
+ ) {
+ logger.info(
+ 'Splitting streams into cached and uncached and using separate sort criteria'
+ );
+ const cachedStreams = streams.filter(
+ (stream) => stream.service?.cached || stream.service === undefined // streams without a service can be considered as 'cached'
+ );
+ const uncachedStreams = streams.filter(
+ (stream) => stream.service?.cached === false
+ );
+
+ // sort the 2 lists separately, and put them after the other, depending on the direction of cached
+ const cachedSorted = cachedStreams.slice().sort((a, b) => {
+ const aKey = this.dynamicSortKey(a, cachedSortCriteria, type);
+ const bKey = this.dynamicSortKey(b, cachedSortCriteria, type);
+ for (let i = 0; i < aKey.length; i++) {
+ if (aKey[i] < bKey[i]) return -1;
+ if (aKey[i] > bKey[i]) return 1;
+ }
+ return 0;
+ });
+
+ const uncachedSorted = uncachedStreams.slice().sort((a, b) => {
+ const aKey = this.dynamicSortKey(a, uncachedSortCriteria, type);
+ const bKey = this.dynamicSortKey(b, uncachedSortCriteria, type);
+ for (let i = 0; i < aKey.length; i++) {
+ if (aKey[i] < bKey[i]) return -1;
+ if (aKey[i] > bKey[i]) return 1;
+ }
+ return 0;
+ });
+
+ if (sortCriteria[0].direction === 'desc') {
+ sortedStreams = [...cachedSorted, ...uncachedSorted];
+ } else {
+ sortedStreams = [...uncachedSorted, ...cachedSorted];
+ }
+ } else {
+ logger.debug(`using sort criteria: ${JSON.stringify(sortCriteria)}`);
+ sortedStreams = streams.slice().sort((a, b) => {
+ const aKey = this.dynamicSortKey(a, sortCriteria, type);
+ const bKey = this.dynamicSortKey(b, sortCriteria, type);
+
+ for (let i = 0; i < aKey.length; i++) {
+ if (aKey[i] < bKey[i]) return -1;
+ if (aKey[i] > bKey[i]) return 1;
+ }
+ return 0;
+ });
+ }
+
+ logger.info(
+ `Sorted ${sortedStreams.length} streams in ${getTimeTakenSincePoint(start)}`
+ );
+ return sortedStreams;
+ }
+
+ private dynamicSortKey(
+ stream: ParsedStream,
+ sortCriteria: SortCriterion[],
+ type: string
+ ): any[] {
+ function keyValue(sortCriterion: SortCriterion, userData: UserData) {
+ const { key, direction } = sortCriterion;
+ const multiplier = direction === 'asc' ? 1 : -1;
+ switch (key) {
+ case 'cached':
+ return multiplier * (stream.service?.cached !== false ? 1 : 0);
+
+ case 'library':
+ return multiplier * (stream.library ? 1 : 0);
+ case 'size':
+ return multiplier * (stream.size ?? 0);
+ case 'seeders':
+ return multiplier * (stream.torrent?.seeders ?? 0);
+ case 'encode': {
+ const index = userData.preferredEncodes?.findIndex(
+ (encode) => encode === (stream.parsedFile?.encode || 'Unknown')
+ );
+ return multiplier * -(index === -1 ? 0 : (index ?? 0));
+ }
+ case 'addon':
+ // find the first occurence of the stream.addon.id in the addons array
+ const idx = userData.presets.findIndex(
+ (p) => JSON.stringify(p) === stream.addon.id
+ );
+ return multiplier * (idx !== -1 ? -idx : 0);
+
+ case 'resolution': {
+ const index = userData.preferredResolutions?.findIndex(
+ (resolution) =>
+ resolution === (stream.parsedFile?.resolution || 'Unknown')
+ );
+ return multiplier * -(index === -1 ? 0 : (index ?? 0));
+ }
+ case 'quality': {
+ const index = userData.preferredQualities?.findIndex(
+ (quality) => quality === (stream.parsedFile?.quality || 'Unknown')
+ );
+ return multiplier * -(index === -1 ? 0 : (index ?? 0));
+ }
+ case 'visualTag': {
+ let minIndex = userData.preferredVisualTags?.length;
+ if (minIndex === undefined) {
+ return 0;
+ }
+ if (!stream.parsedFile) {
+ return 0;
+ }
+ for (const tag of stream.parsedFile?.visualTags || []) {
+ if (VISUAL_TAGS.includes(tag as any)) {
+ const idx = userData.preferredVisualTags?.indexOf(tag as any);
+ if (idx !== undefined && idx !== -1 && idx < minIndex) {
+ minIndex = idx;
+ }
+ }
+ }
+ return multiplier * -minIndex;
+ }
+ case 'audioTag': {
+ let minAudioIndex = userData.preferredAudioTags?.length;
+ if (minAudioIndex === undefined) {
+ return 0;
+ }
+ if (!stream.parsedFile) {
+ return 0;
+ }
+ for (const tag of stream.parsedFile.audioTags) {
+ if (AUDIO_TAGS.includes(tag as any)) {
+ const idx = userData.preferredAudioTags?.indexOf(tag as any);
+ if (idx !== undefined && idx !== -1 && idx < minAudioIndex) {
+ minAudioIndex = idx;
+ }
+ }
+ }
+ return multiplier * -minAudioIndex;
+ }
+ case 'streamType': {
+ const index = userData.preferredStreamTypes?.findIndex(
+ (type) => type === stream.type
+ );
+ return multiplier * -(index === -1 ? 0 : (index ?? 0));
+ }
+ case 'language': {
+ let minLanguageIndex = userData.preferredLanguages?.length;
+ if (minLanguageIndex === undefined) {
+ return 0;
+ }
+ for (const language of stream.parsedFile?.languages || ['Unknown']) {
+ const idx = userData.preferredLanguages?.indexOf(language as any);
+ if (idx !== undefined && idx !== -1 && idx < minLanguageIndex) {
+ minLanguageIndex = idx;
+ }
+ }
+ return multiplier * -minLanguageIndex;
+ }
+ case 'regexPatterns':
+ return (
+ multiplier *
+ -(stream.regexMatched ? stream.regexMatched.index : Infinity)
+ );
+
+ // return (
+ // multiplier *
+ // (stream.regexMatched ? -stream.regexMatched.index : -Infinity)
+ // );
+ // return multiplier * -(stream.regexMatched?.index ?? 0);
+
+ case 'keyword':
+ return multiplier * (stream.keywordMatched ? 1 : 0);
+
+ case 'service': {
+ const index = userData.services?.findIndex(
+ (service) => service.id === stream.service?.id
+ );
+ return multiplier * -(index === -1 ? 0 : (index ?? 0));
+ }
+ default:
+ return 0;
+ }
+ }
+
+ return (
+ sortCriteria.map((sortCriterion) =>
+ keyValue(sortCriterion, this.userData)
+ ) ?? []
+ );
+ }
+
+ private applyModifications(streams: ParsedStream[]): ParsedStream[] {
+ if (this.userData.randomiseResults) {
+ streams.sort(() => Math.random() - 0.5);
+ }
+ if (this.userData.enhanceResults) {
+ streams.forEach((stream) => {
+ if (Math.random() < 0.4) {
+ stream.filename = undefined;
+ stream.parsedFile = undefined;
+ stream.type = 'youtube';
+ stream.ytId = Buffer.from(constants.DEFAULT_YT_ID, 'base64').toString(
+ 'utf-8'
+ );
+ stream.message =
+ 'This stream has been artificially enhanced using the best AI on the market.';
+ }
+ });
+ }
+ return streams;
+ }
+
+ private limitStreams(streams: ParsedStream[]): ParsedStream[] {
+ if (!this.userData.resultLimits) {
+ return streams;
+ }
+
+ // these are our limits
+ const {
+ indexer,
+ releaseGroup,
+ resolution,
+ quality,
+ global,
+ addon,
+ streamType,
+ service,
+ } = this.userData.resultLimits;
+
+ const start = Date.now();
+
+ // Track counts for each category
+ const counts = {
+ indexer: new Map(),
+ releaseGroup: new Map(),
+ resolution: new Map(),
+ quality: new Map(),
+ addon: new Map(),
+ streamType: new Map(),
+ service: new Map(),
+ global: 0,
+ };
+
+ // Keep track of which indexes to remove
+ const indexesToRemove = new Set();
+
+ // Process each stream and check against limits
+ streams.forEach((stream, index) => {
+ // Skip if already marked for removal
+ if (indexesToRemove.has(index)) return;
+
+ // Check global limit first
+ if (global && counts.global >= global) {
+ indexesToRemove.add(index);
+ return;
+ }
+
+ // Check indexer limit
+ if (indexer && stream.indexer) {
+ const count = counts.indexer.get(stream.indexer) || 0;
+ if (count >= indexer) {
+ indexesToRemove.add(index);
+ return;
+ }
+ counts.indexer.set(stream.indexer, count + 1);
+ }
+
+ // Check release group limit
+ if (releaseGroup && stream.parsedFile?.releaseGroup) {
+ const count =
+ counts.releaseGroup.get(stream.parsedFile?.releaseGroup || '') || 0;
+ if (count >= releaseGroup) {
+ indexesToRemove.add(index);
+ return;
+ }
+ counts.releaseGroup.set(stream.parsedFile.releaseGroup, count + 1);
+ }
+
+ // Check resolution limit
+ if (resolution) {
+ const count =
+ counts.resolution.get(stream.parsedFile?.resolution || 'Unknown') ||
+ 0;
+ if (count >= resolution) {
+ indexesToRemove.add(index);
+ return;
+ }
+ counts.resolution.set(
+ stream.parsedFile?.resolution || 'Unknown',
+ count + 1
+ );
+ }
+
+ // Check quality limit
+ if (quality) {
+ const count =
+ counts.quality.get(stream.parsedFile?.quality || 'Unknown') || 0;
+ if (count >= quality) {
+ indexesToRemove.add(index);
+ return;
+ }
+ counts.quality.set(stream.parsedFile?.quality || 'Unknown', count + 1);
+ }
+
+ // Check addon limit
+ if (addon && stream.addon.id) {
+ const count = counts.addon.get(stream.addon.id) || 0;
+ if (count >= addon) {
+ indexesToRemove.add(index);
+ return;
+ }
+ counts.addon.set(stream.addon.id, count + 1);
+ }
+
+ // Check stream type limit
+ if (streamType && stream.type) {
+ const count = counts.streamType.get(stream.type) || 0;
+ if (count >= streamType) {
+ indexesToRemove.add(index);
+ return;
+ }
+ counts.streamType.set(stream.type, count + 1);
+ }
+
+ // Check service limit
+ if (service && stream.service?.id) {
+ const count = counts.service.get(stream.service.id) || 0;
+ if (count >= service) {
+ indexesToRemove.add(index);
+ return;
+ }
+ counts.service.set(stream.service.id, count + 1);
+ }
+
+ // If we got here, increment global count
+ counts.global++;
+ });
+
+ // Filter out the streams that exceeded limits
+ const limitedStreams = streams.filter(
+ (_, index) => !indexesToRemove.has(index)
+ );
+
+ // Log summary of removed streams
+ const removedCount = streams.length - limitedStreams.length;
+ if (removedCount > 0) {
+ logger.info(
+ `Removed ${removedCount} streams due to limits in ${getTimeTakenSincePoint(start)}`
+ );
+ }
+
+ return limitedStreams;
+ }
+
+ private async handlePossibleRecursiveError(error: any) {
+ if (error instanceof PossibleRecursiveRequestError) {
+ if (this.userData.uuid && this.userData.encryptedPassword) {
+ const newData = {
+ ...this.userData,
+ presets: [],
+ };
+ const password = decryptString(this.userData.encryptedPassword).data;
+ if (password) {
+ logger.warn(
+ `resetting addons of user ${this.userData.uuid} due to possible recursive request`
+ );
+ await UserRepository.updateUser(
+ this.userData.uuid,
+ password,
+ newData
+ );
+ }
+ }
+ }
+ }
+
+ private async proxifyStreams(
+ streams: ParsedStream[]
+ ): Promise {
+ if (!this.userData.proxy?.enabled) {
+ return streams;
+ }
+
+ const streamsToProxy = streams
+ .map((stream, index) => ({ stream, index }))
+ .filter(({ stream }) => stream.url && this.shouldProxyStream(stream));
+
+ if (streamsToProxy.length === 0) {
+ return streams;
+ }
+ logger.info(`Proxying ${streamsToProxy.length} streams`);
+
+ const proxy = createProxy(this.userData.proxy);
+
+ const proxiedUrls = streamsToProxy.length
+ ? await proxy.generateUrls(
+ streamsToProxy.map(({ stream }) => ({
+ url: stream.url!,
+ filename: stream.filename,
+ headers: {
+ request: stream.requestHeaders,
+ response: stream.responseHeaders,
+ },
+ }))
+ )
+ : [];
+
+ logger.info(`Generated ${(proxiedUrls || []).length} proxied URLs`);
+
+ const removeIndexes = new Set();
+
+ streamsToProxy.forEach(({ stream, index }, i) => {
+ const proxiedUrl = proxiedUrls?.[i];
+ if (proxiedUrl) {
+ stream.url = proxiedUrl;
+ stream.proxied = true;
+ } else {
+ removeIndexes.add(index);
+ }
+ });
+
+ if (removeIndexes.size > 0) {
+ logger.warn(
+ `Failed to proxy ${removeIndexes.size} streams. Removing them from the list.`
+ );
+ streams = streams.filter((_, index) => !removeIndexes.has(index));
+ }
+
+ return streams;
+ }
+}
diff --git a/packages/core/src/parser/conditions.ts b/packages/core/src/parser/conditions.ts
new file mode 100644
index 00000000..dccb42a3
--- /dev/null
+++ b/packages/core/src/parser/conditions.ts
@@ -0,0 +1,237 @@
+import { Parser } from 'expr-eval';
+import { ParsedStream } from '../db';
+
+export class ConditionParser {
+ private parser: Parser;
+ private previousStreams: ParsedStream[];
+ private totalStreams: ParsedStream[];
+ private previousGroupTimeTaken: number;
+ private totalTimeTaken: number;
+
+ constructor(
+ previousStreams: ParsedStream[],
+ totalStreams: ParsedStream[],
+ previousGroupTimeTaken: number,
+ totalTimeTaken: number,
+ queryType: string
+ ) {
+ this.previousStreams = previousStreams;
+ this.totalStreams = totalStreams;
+ this.previousGroupTimeTaken = previousGroupTimeTaken;
+ this.totalTimeTaken = totalTimeTaken;
+
+ // only allow comparison and logical operators
+ this.parser = new Parser({
+ operators: {
+ comparison: true,
+ logical: true,
+ add: false,
+ concatenate: false,
+ conditional: false,
+ divide: false,
+ factorial: false,
+ multiply: false,
+ power: false,
+ remainder: false,
+ subtract: false,
+ sin: false,
+ cos: false,
+ tan: false,
+ asin: false,
+ acos: false,
+ atan: false,
+ sinh: false,
+ cosh: false,
+ tanh: false,
+ asinh: false,
+ acosh: false,
+ atanh: false,
+ sqrt: false,
+ log: false,
+ ln: false,
+ lg: false,
+ log10: false,
+ abs: false,
+ ceil: false,
+ floor: false,
+ round: false,
+ trunc: false,
+ exp: false,
+ length: false,
+ in: false,
+ random: false,
+ min: false,
+ max: false,
+ assignment: false,
+ fndef: false,
+ cbrt: false,
+ expm1: false,
+ log1p: false,
+ sign: false,
+ log2: false,
+ },
+ });
+
+ this.parser.consts.previousStreams = this.previousStreams;
+ this.parser.consts.totalStreams = this.totalStreams;
+ this.parser.consts.queryType = queryType;
+ this.parser.consts.previousGroupTimeTaken = this.previousGroupTimeTaken;
+ this.parser.consts.totalTimeTaken = this.totalTimeTaken;
+
+ this.parser.functions.regexMatched = function (
+ streams: ParsedStream[],
+ regexName?: string
+ ) {
+ return streams.filter((stream) =>
+ regexName
+ ? stream.regexMatched?.name === regexName
+ : stream.regexMatched
+ );
+ };
+ this.parser.functions.indexer = function (
+ streams: ParsedStream[],
+ indexer: string
+ ) {
+ if (!Array.isArray(streams)) {
+ throw new Error(
+ "Please use one of 'totalStreams' or 'previousStreams' as the first argument"
+ );
+ } else if (typeof indexer !== 'string') {
+ throw new Error('Indexer must be a string');
+ }
+ return streams.filter((stream) => stream.indexer === indexer);
+ };
+ this.parser.functions.resolution = function (
+ streams: ParsedStream[],
+ resolution: string
+ ) {
+ if (!Array.isArray(streams)) {
+ throw new Error(
+ "Please use one of 'totalStreams' or 'previousStreams' as the first argument"
+ );
+ } else if (typeof resolution !== 'string') {
+ throw new Error('Resolution must be a string');
+ }
+ return streams.filter(
+ (stream) => (stream.parsedFile?.resolution || 'Unknown') === resolution
+ );
+ };
+ this.parser.functions.quality = function (
+ streams: ParsedStream[],
+ quality: string
+ ) {
+ if (!Array.isArray(streams)) {
+ throw new Error(
+ "Please use one of 'totalStreams' or 'previousStreams' as the first argument"
+ );
+ } else if (typeof quality !== 'string') {
+ throw new Error('Quality must be a string');
+ }
+ return streams.filter(
+ (stream) => (stream.parsedFile?.quality || 'Unknown') === quality
+ );
+ };
+ this.parser.functions.type = function (
+ streams: ParsedStream[],
+ type: string
+ ) {
+ if (!Array.isArray(streams)) {
+ throw new Error(
+ "Please use one of 'totalStreams' or 'previousStreams' as the first argument"
+ );
+ } else if (typeof type !== 'string') {
+ throw new Error('Type must be a string');
+ }
+ return streams.filter((stream) => stream.type === type);
+ };
+ this.parser.functions.service = function (
+ streams: ParsedStream[],
+ service: string
+ ) {
+ if (!Array.isArray(streams)) {
+ throw new Error(
+ "Please use one of 'totalStreams' or 'previousStreams' as the first argument"
+ );
+ } else if (
+ typeof service !== 'string' ||
+ ![
+ 'realdebrid',
+ 'debridlink',
+ 'alldebrid',
+ 'torbox',
+ 'pikpak',
+ 'seedr',
+ 'offcloud',
+ 'premiumize',
+ 'easynews',
+ 'easydebrid',
+ ].includes(service)
+ ) {
+ throw new Error(
+ 'Service must be a string and one of: realdebrid, debridlink, alldebrid, torbox, pikpak, seedr, offcloud, premiumize, easynews, easydebrid'
+ );
+ }
+ return streams.filter((stream) => stream.service?.id === service);
+ };
+ this.parser.functions.cached = function (streams: ParsedStream[]) {
+ if (!Array.isArray(streams)) {
+ throw new Error(
+ "Please use one of 'totalStreams' or 'previousStreams' as the first argument"
+ );
+ }
+ return streams.filter((stream) => stream.service?.cached === true);
+ };
+ this.parser.functions.uncached = function (streams: ParsedStream[]) {
+ if (!Array.isArray(streams)) {
+ throw new Error(
+ "Please use one of 'totalStreams' or 'previousStreams' as the first argument"
+ );
+ }
+ return streams.filter((stream) => stream.service?.cached === false);
+ };
+ this.parser.functions.releaseGroup = function (
+ streams: ParsedStream[],
+ releaseGroup: string
+ ) {
+ if (!Array.isArray(streams)) {
+ throw new Error(
+ "Please use one of 'totalStreams' or 'previousStreams' as the first argument"
+ );
+ } else if (typeof releaseGroup !== 'string') {
+ throw new Error('Release group must be a string');
+ }
+ return streams.filter(
+ (stream) => stream.parsedFile?.releaseGroup === releaseGroup
+ );
+ };
+ this.parser.functions.count = function (streams: ParsedStream[]) {
+ if (!Array.isArray(streams)) {
+ throw new Error(
+ "Please use one of 'totalStreams' or 'previousStreams' as the first argument"
+ );
+ }
+ return streams.length;
+ };
+ }
+ async parse(condition: string) {
+ return new Promise((resolve, reject) => {
+ const timeout = setTimeout(() => {
+ reject(new Error('Condition parsing timed out'));
+ }, 1);
+
+ try {
+ const result = this.parser.evaluate(condition);
+ clearTimeout(timeout);
+ resolve(result);
+ } catch (error) {
+ clearTimeout(timeout);
+ reject(error);
+ }
+ });
+ }
+
+ static async testParse(condition: string) {
+ const parser = new ConditionParser([], [], 0, 0, 'movie');
+ return await parser.parse(condition);
+ }
+}
diff --git a/packages/core/src/parser/file.ts b/packages/core/src/parser/file.ts
new file mode 100644
index 00000000..ab442920
--- /dev/null
+++ b/packages/core/src/parser/file.ts
@@ -0,0 +1,85 @@
+import { PARSE_REGEX } from './regex';
+import * as PTT from 'parse-torrent-title';
+import { ParsedFile } from '../db';
+
+function matchPattern(
+ filename: string,
+ patterns: Record
+): string | undefined {
+ return Object.entries(patterns).find(([_, pattern]) =>
+ pattern.test(filename)
+ )?.[0];
+}
+
+function matchMultiplePatterns(
+ filename: string,
+ patterns: Record
+): string[] {
+ return Object.entries(patterns)
+ .filter(([_, pattern]) => pattern.test(filename))
+ .map(([tag]) => tag);
+}
+
+class FileParser {
+ static parse(filename: string): ParsedFile {
+ filename = filename.replace(/\s+/g, '.').replace(/^\.+|\.+$/g, '');
+ const resolution = matchPattern(filename, PARSE_REGEX.resolutions);
+ const quality = matchPattern(filename, PARSE_REGEX.qualities);
+ const encode = matchPattern(filename, PARSE_REGEX.encodes);
+ const audioChannels = matchMultiplePatterns(
+ filename,
+ PARSE_REGEX.audioChannels
+ );
+ const visualTags = matchMultiplePatterns(filename, PARSE_REGEX.visualTags);
+ const audioTags = matchMultiplePatterns(filename, PARSE_REGEX.audioTags);
+ const languages = matchMultiplePatterns(filename, PARSE_REGEX.languages);
+
+ const getPaddedNumber = (number: number, length: number) =>
+ number.toString().padStart(length, '0');
+
+ const parsed = PTT.parse(filename);
+ const releaseGroup = parsed.group;
+ const title = parsed.title;
+ const year = parsed.year ? parsed.year.toString() : undefined;
+ const season = parsed.season;
+ const seasons = parsed.seasons;
+ const episode = parsed.episode;
+ const formattedSeasonString = seasons?.length
+ ? seasons.length === 1
+ ? `S${getPaddedNumber(seasons[0], 2)}`
+ : `S${getPaddedNumber(seasons[0], 2)}-${getPaddedNumber(
+ seasons[seasons.length - 1],
+ 2
+ )}`
+ : season
+ ? `S${getPaddedNumber(season, 2)}`
+ : undefined;
+ const formattedEpisodeString = episode
+ ? `E${getPaddedNumber(episode, 2)}`
+ : undefined;
+
+ const seasonEpisode = [
+ formattedSeasonString,
+ formattedEpisodeString,
+ ].filter((v) => v !== undefined);
+
+ return {
+ resolution,
+ quality,
+ languages,
+ encode,
+ audioChannels,
+ audioTags,
+ visualTags,
+ releaseGroup,
+ title,
+ year,
+ season,
+ seasons,
+ episode,
+ seasonEpisode,
+ };
+ }
+}
+
+export default FileParser;
diff --git a/packages/core/src/parser/index.ts b/packages/core/src/parser/index.ts
new file mode 100644
index 00000000..0a07f956
--- /dev/null
+++ b/packages/core/src/parser/index.ts
@@ -0,0 +1,2 @@
+export { default as FileParser } from './file';
+export { default as StreamParser } from './streams';
diff --git a/packages/parser/src/regex.ts b/packages/core/src/parser/regex.ts
similarity index 74%
rename from packages/parser/src/regex.ts
rename to packages/core/src/parser/regex.ts
index a4ed5141..5492ad10 100644
--- a/packages/parser/src/regex.ts
+++ b/packages/core/src/parser/regex.ts
@@ -1,10 +1,47 @@
+import { AUDIO_TAGS, QUALITIES, RESOLUTIONS } from '../utils/constants';
+import { VISUAL_TAGS } from '../utils/constants';
+import { ENCODES } from '../utils/constants';
+import { LANGUAGES } from '../utils/constants';
+import { AUDIO_CHANNELS } from '../utils/constants';
const createRegex = (pattern: string): RegExp =>
new RegExp(`(?
createRegex(`${pattern}(?![ .\\-_]?sub(title)?s?)`);
-export const PARSE_REGEX = {
+type PARSE_REGEX = {
+ resolutions: Omit, 'Unknown'> & {
+ Unknown?: RegExp;
+ };
+ qualities: Omit, 'Unknown'> & {
+ Unknown?: RegExp;
+ };
+ visualTags: Omit<
+ Record<(typeof VISUAL_TAGS)[number], RegExp>,
+ 'Unknown' | 'HDR+DV'
+ > & {
+ Unknown?: RegExp;
+ 'HDR+DV'?: RegExp;
+ };
+ audioTags: Omit, 'Unknown'> & {
+ Unknown?: RegExp;
+ };
+ audioChannels: Omit<
+ Record<(typeof AUDIO_CHANNELS)[number], RegExp>,
+ 'Unknown'
+ > & {
+ Unknown?: RegExp;
+ };
+ languages: Omit, 'Unknown'> & {
+ Unknown?: RegExp;
+ };
+ encodes: Omit, 'Unknown'> & {
+ Unknown?: RegExp;
+ };
+ releaseGroup: RegExp;
+};
+
+export const PARSE_REGEX: PARSE_REGEX = {
resolutions: {
'2160p': createRegex(
'(bd|hd|m)?(4k|2160(p|i)?)|u(ltra)?[ .\\-_]?hd|3840\s?x\s?(\d{4})'
@@ -16,7 +53,11 @@ export const PARSE_REGEX = {
'(bd|hd|m)?(1080(p|i)?)|f(ull)?[ .\\-_]?hd|1920\s?x\s?(\d{3,4})'
),
'720p': createRegex('(bd|hd|m)?(720(p|i)?)|hd|1280\s?x\s?(\d{3,4})'),
+ '576p': createRegex('(bd|hd|m)?(576(p|i)?)'),
'480p': createRegex('(bd|hd|m)?(480(p|i)?)|sd'),
+ '360p': createRegex('(bd|hd|m)?(360(p|i)?)'),
+ '240p': createRegex('(bd|hd|m)?(240(p|i)?)'),
+ '144p': createRegex('(bd|hd|m)?(144(p|i)?)'),
},
qualities: {
'BluRay REMUX':
@@ -58,22 +99,30 @@ export const PARSE_REGEX = {
),
'DTS-HD MA': createRegex('dts[ .\\-_]?hd[ .\\-_]?ma'),
'DTS-HD': createRegex('dts[ .\\-_]?hd(?![ .\\-_]?ma)'),
- DTS: createRegex('dts(?![ .\\-_]?hd[ .\\-_]?ma|[ .\\-_]?hd)'),
+ 'DTS-ES': createRegex('dts[ .\\-_]?es'),
+ DTS: createRegex('dts(?![ .\\-_]?hd[ .\\-_]?ma|[ .\\-_]?hd|[ .\\-_]?es)'),
TrueHD: createRegex('true[ .\\-_]?hd'),
- 5.1: createRegex(
- '(d(olby)?[ .\\-_]?d(igital)?[ .\\-_]?(p(lus)?|\\+)?)?5[ .\\-_]?1(ch)?'
- ),
- 7.1: createRegex(
- '(d(olby)?[ .\\-_]?d(igital)?[ .\\-_]?(p(lus)?|\\+)?)?7[ .\\-_]?1(ch)?'
- ),
+ OPUS: createRegex('opus'),
AAC: createRegex('q?aac(?:[ .\\-_]?2)?'),
FLAC: createRegex('flac(?:[ .\\-_]?(lossless|2\\.0|x[2-4]))?'),
},
+ audioChannels: {
+ '2.0': createRegex('(2[ .\\-_]?0)(ch)?'),
+ '5.1': createRegex(
+ '(d(olby)?[ .\\-_]?d(igital)?[ .\\-_]?(p(lus)?|\\+)?)?5[ .\\-_]?1(ch)?'
+ ),
+ '6.1': createRegex(
+ '(d(olby)?[ .\\-_]?d(igital)?[ .\\-_]?(p(lus)?|\\+)?)?6[ .\\-_]?1(ch)?'
+ ),
+ '7.1': createRegex(
+ '(d(olby)?[ .\\-_]?d(igital)?[ .\\-_]?(p(lus)?|\\+)?)?7[ .\\-_]?1(ch)?'
+ ),
+ },
encodes: {
HEVC: createRegex('hevc[ .\\-_]?(10)?|[xh][ .\\-_]?265'),
AVC: createRegex('avc|[xh][ .\\-_]?264'),
AV1: createRegex('av1'),
- Xvid: createRegex('xvid'),
+ XviD: createRegex('xvid'),
DivX: createRegex('divx|dvix'),
'H-OU': createRegex('h?(alf)?[ .\\-_]?(ou|over[ .\\-_]?under)'),
'H-SBS': createRegex('h?(alf)?[ .\\-_]?(sbs|side[ .\\-_]?by[ .\\-_]?side)'),
@@ -85,18 +134,18 @@ export const PARSE_REGEX = {
),
Dubbed: createLanguageRegex('dub(bed)?'),
English: createLanguageRegex('english|eng'),
- Japanese: createLanguageRegex('japanese|jap'),
+ Japanese: createLanguageRegex('japanese|jap|jpn'),
Chinese: createLanguageRegex('chinese|chi'),
Russian: createLanguageRegex('russian|rus'),
Arabic: createLanguageRegex('arabic|ara'),
Portuguese: createLanguageRegex('portuguese|por'),
Spanish: createLanguageRegex('spanish|spa|esp'),
- French: createLanguageRegex('french|fra'),
+ French: createLanguageRegex('french|fra|fr|vf|vff|vfi|vf2|vfq|truefrench'),
German: createLanguageRegex('german|ger'),
Italian: createLanguageRegex('italian|ita'),
Korean: createLanguageRegex('korean|kor'),
Hindi: createLanguageRegex('hindi|hin'),
- Bengali: createLanguageRegex('bengali|ben'),
+ Bengali: createLanguageRegex('bengali|ben(?![ .\\-_]?the[ .\\-_]?men)'),
Punjabi: createLanguageRegex('punjabi|pan'),
Marathi: createLanguageRegex('marathi|mar'),
Gujarati: createLanguageRegex('gujarati|guj'),
diff --git a/packages/core/src/parser/streams.ts b/packages/core/src/parser/streams.ts
new file mode 100644
index 00000000..f1464e59
--- /dev/null
+++ b/packages/core/src/parser/streams.ts
@@ -0,0 +1,484 @@
+import { Stream, ParsedStream, Addon } from '../db';
+import { constants, createLogger, FULL_LANGUAGE_MAPPING } from '../utils';
+import FileParser from './file';
+const logger = createLogger('parser');
+class StreamParser {
+ get errorRegexes(): { pattern: RegExp; message: string }[] | undefined {
+ return [
+ {
+ pattern: /invalid\s+\w+\s+(account|apikey|token)/i,
+ message: 'Invalid account or apikey or token',
+ },
+ ];
+ }
+ protected get filenameRegex(): RegExp | undefined {
+ return undefined;
+ }
+ protected get folderNameRegex(): RegExp | undefined {
+ return undefined;
+ }
+
+ protected get sizeRegex(): RegExp | undefined {
+ return /(\d+(\.\d+)?)\s?(KB|MB|GB|TB)/i;
+ }
+ protected get sizeK(): 1024 | 1000 {
+ return 1024;
+ }
+
+ protected get seedersRegex(): RegExp | undefined {
+ return /[👥👤]\s*(\d+)/u;
+ }
+
+ protected get indexerEmojis(): string[] {
+ return ['🌐', '⚙️', '🔗', '🔎', '🔍', '☁️'];
+ }
+
+ protected get indexerRegex(): RegExp | undefined {
+ return this.getRegexForTextAfterEmojis(this.indexerEmojis);
+ }
+
+ protected get ageRegex(): RegExp | undefined {
+ return undefined;
+ }
+
+ protected getRegexForTextAfterEmojis(emojis: string[]): RegExp {
+ return new RegExp(
+ `(?:${emojis.join('|')})\\s*([^\\p{Emoji_Presentation}\\n]*?)(?=\\p{Emoji_Presentation}|$|\\n)`,
+ 'u'
+ );
+ }
+
+ constructor(protected readonly addon: Addon) {}
+
+ parse(stream: Stream): ParsedStream {
+ let parsedStream: ParsedStream = {
+ addon: this.addon,
+ type: 'http',
+ url: this.applyUrlModifications(stream.url),
+ externalUrl: stream.externalUrl,
+ ytId: stream.ytId,
+ requestHeaders: stream.behaviorHints?.proxyHeaders?.request,
+ responseHeaders: stream.behaviorHints?.proxyHeaders?.response,
+ notWebReady: stream.behaviorHints?.notWebReady,
+ videoHash: stream.behaviorHints?.videoHash,
+ originalName: stream.name,
+ originalDescription: stream.description || stream.title,
+ };
+
+ stream.description = stream.description || stream.title;
+
+ this.raiseErrorIfNecessary(stream, parsedStream);
+
+ parsedStream.error = this.getError(stream, parsedStream);
+ if (parsedStream.error) {
+ parsedStream.type = constants.ERROR_STREAM_TYPE;
+ return parsedStream;
+ }
+
+ parsedStream.filename = this.getFilename(stream, parsedStream);
+ parsedStream.folderName = this.getFolder(stream, parsedStream);
+ parsedStream.size = this.getSize(stream, parsedStream);
+ parsedStream.folderSize = this.getFolderSize(stream, parsedStream);
+ parsedStream.indexer = this.getIndexer(stream, parsedStream);
+ parsedStream.service = this.getService(stream, parsedStream);
+ parsedStream.duration = this.getDuration(stream, parsedStream);
+ parsedStream.type = this.getStreamType(
+ stream,
+ parsedStream.service,
+ parsedStream
+ );
+ parsedStream.library = this.getInLibrary(stream, parsedStream);
+ parsedStream.age = this.getAge(stream, parsedStream);
+ parsedStream.message = this.getMessage(stream, parsedStream);
+
+ if (parsedStream.filename) {
+ parsedStream.parsedFile = FileParser.parse(parsedStream.filename);
+ parsedStream.parsedFile.languages = Array.from(
+ new Set([
+ ...parsedStream.parsedFile.languages,
+ ...this.getLanguages(stream, parsedStream),
+ ])
+ );
+ }
+
+ if (parsedStream.folderName && parsedStream.parsedFile) {
+ const parsedFolder = FileParser.parse(parsedStream.folderName);
+ parsedStream.parsedFile = {
+ ...parsedStream.parsedFile,
+ title: parsedFolder.title, // prefer titles from the folder name if it exists
+ };
+ }
+
+ parsedStream.torrent = {
+ infoHash:
+ parsedStream.type === 'p2p'
+ ? stream.infoHash
+ : this.getInfoHash(stream, parsedStream),
+ seeders: this.getSeeders(stream, parsedStream),
+ sources: stream.sources,
+ fileIdx: stream.fileIdx,
+ };
+
+ return parsedStream;
+ }
+
+ protected applyUrlModifications(url: string | undefined): string | undefined {
+ return url;
+ }
+
+ protected raiseErrorIfNecessary(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ) {
+ if (!this.errorRegexes) {
+ return;
+ }
+ for (const errorRegex of this.errorRegexes) {
+ if (errorRegex.pattern.test(stream.description || stream.title || '')) {
+ throw new Error(errorRegex.message);
+ }
+ }
+ }
+
+ protected getError(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): ParsedStream['error'] | undefined {
+ return undefined;
+ }
+
+ protected getFilename(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ let filename = stream.behaviorHints?.filename;
+
+ if (filename) {
+ return filename;
+ }
+
+ const description = stream.description || stream.title;
+ if (!description) {
+ return undefined;
+ }
+
+ if (this.filenameRegex) {
+ const match = description.match(this.filenameRegex);
+ if (match) {
+ return match[1];
+ }
+ }
+
+ // attempt to find a filename by finding the most suitable line that has more info
+ const potentialFilenames = description
+ .split('\n')
+ .filter((line) => line.trim() !== '')
+ .splice(0, 5);
+
+ for (const line of potentialFilenames) {
+ const parsed = FileParser.parse(line);
+ if (parsed.year || (parsed.season && parsed.episode) || parsed.episode) {
+ filename = line;
+ break;
+ }
+ }
+
+ if (!filename) {
+ filename = description.split('\n')[0];
+ }
+ return filename
+ ?.trim()
+ ?.replace(/^\p{Emoji_Presentation}+/gu, '')
+ ?.replace(/^[^:]+:\s*/g, '');
+ }
+
+ protected getFolder(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ if (this.folderNameRegex) {
+ const match = stream.description?.match(this.folderNameRegex);
+ if (match) {
+ return match[1];
+ }
+ }
+ return undefined;
+ }
+
+ protected getSize(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): number | undefined {
+ let description = stream.description || stream.title;
+ if (currentParsedStream.filename && description) {
+ description = description.replace(currentParsedStream.filename, '');
+ }
+ if (currentParsedStream.folderName && description) {
+ description = description.replace(currentParsedStream.folderName, '');
+ }
+ let size =
+ stream.behaviorHints?.videoSize ||
+ (stream as any).size ||
+ (stream as any).sizeBytes ||
+ (stream as any).sizebytes ||
+ (description && this.calculateBytesFromSizeString(description)) ||
+ (stream.name && this.calculateBytesFromSizeString(stream.name));
+
+ if (typeof size === 'string') {
+ size = parseInt(size);
+ } else if (typeof size === 'number') {
+ size = Math.round(size);
+ }
+
+ return size;
+ }
+
+ protected getFolderSize(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): number | undefined {
+ return undefined;
+ }
+
+ protected getSeeders(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): number | undefined {
+ const regex = this.seedersRegex;
+ if (!regex) {
+ return undefined;
+ }
+ const match = stream.description?.match(regex);
+ if (match) {
+ return parseInt(match[1]);
+ }
+
+ return undefined;
+ }
+
+ protected getAge(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ const regex = this.ageRegex;
+ if (!regex) {
+ return undefined;
+ }
+ const match = stream.description?.match(regex);
+ if (match) {
+ return match[1];
+ }
+
+ return undefined;
+ }
+
+ protected getIndexer(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ const regex = this.indexerRegex;
+ if (!regex) {
+ return undefined;
+ }
+ const match = stream.description?.match(regex);
+ if (match) {
+ return match[1];
+ }
+
+ return undefined;
+ }
+
+ protected getMessage(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ return undefined;
+ }
+
+ protected getService(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): ParsedStream['service'] | undefined {
+ return this.parseServiceData(stream.name || '');
+ }
+
+ protected getInfoHash(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ return stream.url
+ ? stream.url.match(/(?<=[-/[(;:&])[a-fA-F0-9]{40}(?=[-\]\)/:;&])/)?.[0]
+ : undefined;
+ }
+
+ protected getDuration(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): number | undefined {
+ // Regular expression to match different formats of time durations
+ const regex =
+ /(? {
+ const possibleLanguages = FULL_LANGUAGE_MAPPING.filter(
+ (language) => language.flag === flag
+ );
+
+ const language = (
+ possibleLanguages.find((l) => l.flag_priority) || possibleLanguages[0]
+ ).english_name
+ ?.split('(')?.[0]
+ ?.trim();
+ if (language && constants.LANGUAGES.includes(language as any)) {
+ return language;
+ }
+ return undefined;
+ })
+ .filter((language) => language !== undefined);
+ return languages;
+ }
+
+ protected convertISO6392ToLanguage(code: string): string | undefined {
+ const lang = FULL_LANGUAGE_MAPPING.find(
+ (language) => language.iso_639_2 === code
+ );
+ return lang?.english_name?.split('(')?.[0]?.trim();
+ }
+
+ protected getInLibrary(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): boolean {
+ return this.addon.library ?? false;
+ }
+
+ protected calculateBytesFromSizeString(size: string): number | undefined {
+ const k = this.sizeK;
+ if (!this.sizeRegex) {
+ return undefined;
+ }
+ const sizePattern = this.sizeRegex;
+ const match = size.match(sizePattern);
+ if (!match) return 0;
+ const value = parseFloat(match[1]);
+ const unit = match[3];
+
+ switch (unit.toUpperCase()) {
+ case 'TB':
+ return value * k * k * k * k;
+ case 'GB':
+ return value * k * k * k;
+ case 'MB':
+ return value * k * k;
+ case 'KB':
+ return value * k;
+ default:
+ return 0;
+ }
+ }
+
+ protected parseServiceData(
+ string: string
+ ): ParsedStream['service'] | undefined {
+ const cleanString = string.replace(/web-?dl/i, '');
+ const services = constants.SERVICE_DETAILS;
+ const cachedSymbols = ['+', '⚡', '🚀', 'cached'];
+ const uncachedSymbols = ['⏳', 'download', 'UNCACHED'];
+ let streamService: ParsedStream['service'] | undefined;
+ Object.values(services).forEach((service) => {
+ // for each service, generate a regexp which creates a regex with all known names separated by |
+ const regex = new RegExp(
+ `(^|(? string.includes(symbol))) {
+ cached = false;
+ }
+ // check if any of the cachedSymbols are in the string
+ else if (cachedSymbols.some((symbol) => string.includes(symbol))) {
+ cached = true;
+ }
+
+ streamService = {
+ id: service.id,
+ cached: cached,
+ };
+ }
+ });
+ return streamService;
+ }
+}
+
+export default StreamParser;
diff --git a/packages/core/src/presets/aiostreams.ts b/packages/core/src/presets/aiostreams.ts
new file mode 100644
index 00000000..5868d698
--- /dev/null
+++ b/packages/core/src/presets/aiostreams.ts
@@ -0,0 +1,151 @@
+import {
+ Addon,
+ Option,
+ UserData,
+ ParsedStream,
+ Stream,
+ AIOStream,
+} from '../db';
+import { Preset, baseOptions } from './preset';
+import { Env, formatZodError, RESOURCES } from '../utils';
+import { StreamParser } from '../parser';
+import { createLogger } from '../utils';
+
+const logger = createLogger('parser');
+
+class AIOStreamsStreamParser extends StreamParser {
+ override parse(stream: Stream): ParsedStream {
+ const aioStream = stream as AIOStream;
+ const parsed = AIOStream.safeParse(aioStream);
+ if (!parsed.success) {
+ logger.error(
+ `Stream from AIOStream was not detected as a valid stream: ${formatZodError(parsed.error)}`
+ );
+ throw new Error('Invalid stream');
+ }
+ return {
+ addon: {
+ ...this.addon,
+ name: `${this.addon.name} | ${aioStream.streamData?.addon ?? ''}`,
+ },
+ error: aioStream.streamData?.error,
+ type: aioStream.streamData?.type ?? 'http',
+ url: aioStream.url,
+ externalUrl: aioStream.externalUrl,
+ ytId: aioStream.ytId,
+ requestHeaders: aioStream.behaviorHints?.proxyHeaders?.request,
+ responseHeaders: aioStream.behaviorHints?.proxyHeaders?.response,
+ notWebReady: aioStream.behaviorHints?.notWebReady,
+ videoHash: aioStream.behaviorHints?.videoHash,
+ filename: aioStream.streamData?.filename,
+ folderName: aioStream.streamData?.folderName,
+ size: aioStream.streamData?.size,
+ folderSize: aioStream.streamData?.folderSize,
+ indexer: aioStream.streamData?.indexer,
+ service: aioStream.streamData?.service,
+ duration: aioStream.streamData?.duration,
+ library: aioStream.streamData?.library ?? false,
+ age: aioStream.streamData?.age,
+ message: aioStream.streamData?.message,
+ torrent: aioStream.streamData?.torrent,
+ parsedFile: aioStream.streamData?.parsedFile,
+ keywordMatched: aioStream.streamData?.keywordMatched,
+ regexMatched: aioStream.streamData?.regexMatched,
+ originalName: aioStream.name,
+ originalDescription: aioStream.description || stream.title,
+ };
+ }
+}
+
+export class AIOStreamsPreset extends Preset {
+ static override getParser(): typeof StreamParser {
+ return AIOStreamsStreamParser;
+ }
+
+ static override get METADATA() {
+ const options: Option[] = [
+ {
+ id: 'name',
+ name: 'Name',
+ description: 'What to call this addon',
+ type: 'string',
+ required: true,
+ default: 'AIOStreams',
+ },
+ {
+ id: 'manifestUrl',
+ name: 'Manifest URL',
+ description: 'Provide the Manifest URL for this AIOStreams addon.',
+ type: 'url',
+ required: true,
+ },
+ {
+ id: 'timeout',
+ name: 'Timeout',
+ description: 'The timeout for this addon',
+ type: 'number',
+ default: Env.DEFAULT_TIMEOUT,
+ constraints: {
+ min: Env.MIN_TIMEOUT,
+ max: Env.MAX_TIMEOUT,
+ },
+ },
+ {
+ id: 'resources',
+ name: 'Resources',
+ description:
+ 'Optionally override the resources that are fetched from this addon ',
+ type: 'multi-select',
+ required: false,
+ default: undefined,
+ options: RESOURCES.map((resource) => ({
+ label: resource,
+ value: resource,
+ })),
+ },
+ ];
+
+ return {
+ ID: 'aiostreams',
+ NAME: 'AIOStreams',
+ LOGO: 'https://raw.githubusercontent.com/Viren070/AIOStreams/refs/heads/main/packages/frontend/public/assets/logo.png',
+ URL: '',
+ TIMEOUT: Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION: 'Wrap AIOStreams within AIOStreams!',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [],
+ SUPPORTED_RESOURCES: [],
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ if (!options.manifestUrl.endsWith('/manifest.json')) {
+ throw new Error('Invalid manifest URL');
+ }
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: options.manifestUrl.replace('stremio://', 'https://'),
+ enabled: true,
+ library: false,
+ resources: options.resources || undefined,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/animeKitsu.ts b/packages/core/src/presets/animeKitsu.ts
new file mode 100644
index 00000000..3c178c40
--- /dev/null
+++ b/packages/core/src/presets/animeKitsu.ts
@@ -0,0 +1,63 @@
+import { Addon, Option, UserData } from '../db';
+import { Preset, baseOptions } from './preset';
+import { constants, Env } from '../utils';
+
+export class AnimeKitsuPreset extends Preset {
+ static override get METADATA() {
+ const supportedResources = [
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ ];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'Anime Kitsu',
+ supportedResources,
+ Env.DEFAULT_ANIME_KITSU_TIMEOUT
+ ),
+ ];
+
+ return {
+ ID: 'anime-kitsu',
+ NAME: 'Anime Kitsu',
+ LOGO: 'https://i.imgur.com/7N6XGoO.png',
+ URL: Env.ANIME_KITSU_URL,
+ TIMEOUT: Env.DEFAULT_ANIME_KITSU_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_ANIME_KITSU_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION: 'Anime catalog using Kitsu',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ const baseUrl = options.url
+ ? new URL(options.url).origin
+ : Env.ANIME_KITSU_URL;
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: `${baseUrl}/manifest.json`,
+ enabled: true,
+ library: false,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/comet.ts b/packages/core/src/presets/comet.ts
new file mode 100644
index 00000000..49d99b5e
--- /dev/null
+++ b/packages/core/src/presets/comet.ts
@@ -0,0 +1,190 @@
+import { Addon, Option, UserData, Resource } from '../db';
+import { baseOptions, Preset } from './preset';
+import { Env } from '../utils';
+import { constants, ServiceId } from '../utils';
+import { StreamParser } from '../parser';
+
+class CometStreamParser extends StreamParser {
+ override applyUrlModifications(url: string | undefined): string | undefined {
+ if (!url) {
+ return url;
+ }
+ if (
+ Env.FORCE_COMET_HOSTNAME !== undefined ||
+ Env.FORCE_COMET_PORT !== undefined ||
+ Env.FORCE_COMET_PROTOCOL !== undefined
+ ) {
+ // modify the URL according to settings, needed when using a local URL for requests but a public stream URL is needed.
+ const urlObj = new URL(url);
+
+ if (Env.FORCE_COMET_PROTOCOL !== undefined) {
+ urlObj.protocol = Env.FORCE_COMET_PROTOCOL;
+ }
+ if (Env.FORCE_COMET_PORT !== undefined) {
+ urlObj.port = Env.FORCE_COMET_PORT.toString();
+ }
+ if (Env.FORCE_COMET_HOSTNAME !== undefined) {
+ urlObj.hostname = Env.FORCE_COMET_HOSTNAME;
+ }
+ return urlObj.toString();
+ }
+ return url;
+ }
+}
+
+export class CometPreset extends Preset {
+ static override getParser(): typeof StreamParser {
+ return CometStreamParser;
+ }
+
+ static override get METADATA() {
+ const supportedServices: ServiceId[] = [
+ constants.REALDEBRID_SERVICE,
+ constants.PREMIUMIZE_SERVICE,
+ constants.ALLEDEBRID_SERVICE,
+ constants.TORBOX_SERVICE,
+ constants.EASYDEBRID_SERVICE,
+ constants.DEBRIDLINK_SERVICE,
+ constants.OFFCLOUD_SERVICE,
+ constants.PIKPAK_SERVICE,
+ ];
+
+ const supportedResources = [constants.STREAM_RESOURCE];
+
+ const options: Option[] = [
+ ...baseOptions('Comet', supportedResources, Env.DEFAULT_COMET_TIMEOUT),
+ {
+ id: 'includeP2P',
+ name: 'Include P2P',
+ description: 'Include P2P results, even if a debrid service is enabled',
+ type: 'boolean',
+ default: false,
+ },
+ {
+ id: 'removeTrash',
+ name: 'Remove Trash',
+ description:
+ 'Remove all trash from results (Adult Content, CAM, Clean Audio, PDTV, R5, Screener, Size, Telecine and Telesync)',
+ type: 'boolean',
+ default: true,
+ },
+ {
+ id: 'services',
+ name: 'Services',
+ description:
+ 'Optionally override the services that are used. If not specified, then the services that are enabled and supported will be used.',
+ type: 'multi-select',
+ required: false,
+ options: supportedServices.map((service) => ({
+ value: service,
+ label: constants.SERVICE_DETAILS[service].name,
+ })),
+ default: undefined,
+ emptyIsUndefined: true,
+ },
+ ];
+
+ return {
+ ID: 'comet',
+ NAME: 'Comet',
+ LOGO: 'https://i.imgur.com/jmVoVMu.jpeg',
+ URL: Env.COMET_URL,
+ TIMEOUT: Env.DEFAULT_COMET_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_COMET_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: supportedServices,
+ DESCRIPTION: "Stremio's fastest Torrent/Debrid addon",
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [
+ constants.P2P_STREAM_TYPE,
+ constants.DEBRID_STREAM_TYPE,
+ ],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ // url can either be something like https://torrentio.com/ or it can be a custom manifest url.
+ // if it is a custom manifest url, return a single addon with the custom manifest url.
+ if (options?.url?.endsWith('/manifest.json')) {
+ return [this.generateAddon(userData, options, undefined)];
+ }
+
+ const usableServices = this.getUsableServices(userData, options.services);
+ // if no services are usable, use p2p
+ if (!usableServices || usableServices.length === 0) {
+ return [this.generateAddon(userData, options, undefined)];
+ }
+
+ let addons = usableServices.map((service) =>
+ this.generateAddon(userData, options, service.id)
+ );
+
+ if (options.includeP2P) {
+ addons.push(this.generateAddon(userData, options, undefined));
+ }
+
+ return addons;
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record,
+ serviceId?: ServiceId
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: serviceId
+ ? `${options.name || this.METADATA.NAME} ${constants.SERVICE_DETAILS[serviceId].shortName}`
+ : options.name || this.METADATA.NAME,
+ manifestUrl: this.generateManifestUrl(userData, options, serviceId),
+ enabled: true,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+
+ private static generateManifestUrl(
+ userData: UserData,
+ options: Record,
+ serviceId: ServiceId | undefined
+ ) {
+ let url = options.url || this.METADATA.URL;
+ if (url.endsWith('/manifest.json')) {
+ return url;
+ }
+ url = url.replace(/\/$/, '');
+ const configString = this.base64EncodeJSON({
+ maxResultsPerResolution: 0,
+ maxSize: 0,
+ cachedOnly: false,
+ removeTrash: options.removeTrash ?? true,
+ resultFormat: ['all'],
+ debridService: serviceId || 'torrent',
+ debridApiKey: serviceId
+ ? this.getServiceCredential(serviceId, userData, {
+ [constants.OFFCLOUD_SERVICE]: (credentials: any) =>
+ `${credentials.email}:${credentials.password}`,
+ [constants.PIKPAK_SERVICE]: (credentials: any) =>
+ `${credentials.email}:${credentials.password}`,
+ })
+ : '',
+ debridStreamProxyPassword: '',
+ languages: { required: [], exclude: [], preferred: [] },
+ resolutions: {},
+ options: {
+ remove_ranks_under: -10000000000,
+ allow_english_in_languages: false,
+ remove_unknown_languages: false,
+ },
+ });
+
+ return `${url}${configString ? '/' + configString : ''}/manifest.json`;
+ }
+}
diff --git a/packages/core/src/presets/custom.ts b/packages/core/src/presets/custom.ts
new file mode 100644
index 00000000..b9ac170f
--- /dev/null
+++ b/packages/core/src/presets/custom.ts
@@ -0,0 +1,109 @@
+import { Addon, Option, UserData } from '../db';
+import { Preset, baseOptions } from './preset';
+import { Env, RESOURCES } from '../utils';
+
+export class CustomPreset extends Preset {
+ static override get METADATA() {
+ const options: Option[] = [
+ {
+ id: 'name',
+ name: 'Name',
+ description: 'What to call this addon',
+ type: 'string',
+ required: true,
+ default: 'Custom Addon',
+ },
+ {
+ id: 'manifestUrl',
+ name: 'Manifest URL',
+ description: 'Provide the Manifest URL for this custom addon.',
+ type: 'url',
+ required: true,
+ },
+ {
+ id: 'libraryAddon',
+ name: 'Library Addon',
+ description:
+ 'Whether to mark this addon as a library addon. This will result in all streams from this addon being marked as library streams.',
+ type: 'boolean',
+ required: false,
+ default: false,
+ },
+ {
+ id: 'streamPassthrough',
+ name: 'Stream Passthrough',
+ description:
+ 'Whether to pass through the stream formatting. This means your formatting will not be applied and original stream formatting is retained.',
+ type: 'boolean',
+ },
+ {
+ id: 'timeout',
+ name: 'Timeout',
+ description: 'The timeout for this addon',
+ type: 'number',
+ default: Env.DEFAULT_TIMEOUT,
+ constraints: {
+ min: Env.MIN_TIMEOUT,
+ max: Env.MAX_TIMEOUT,
+ },
+ },
+ {
+ id: 'resources',
+ name: 'Resources',
+ description:
+ 'Optionally override the resources that are fetched from this addon ',
+ type: 'multi-select',
+ required: false,
+ default: undefined,
+ options: RESOURCES.map((resource) => ({
+ label: resource,
+ value: resource,
+ })),
+ },
+ ];
+
+ return {
+ ID: 'custom',
+ NAME: 'Custom',
+ LOGO: '',
+ URL: '',
+ TIMEOUT: Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION: 'Add your own addon by providing its Manifest URL.',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [],
+ SUPPORTED_RESOURCES: [],
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ if (!options.manifestUrl.endsWith('/manifest.json')) {
+ throw new Error('Invalid manifest URL');
+ }
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: options.manifestUrl,
+ enabled: true,
+ library: options.libraryAddon ?? false,
+ resources: options.resources || undefined,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ streamPassthrough: options.streamPassthrough ?? false,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/dcUniverse.ts b/packages/core/src/presets/dcUniverse.ts
new file mode 100644
index 00000000..5a2c8f9d
--- /dev/null
+++ b/packages/core/src/presets/dcUniverse.ts
@@ -0,0 +1,125 @@
+import { Addon, Option, UserData } from '../db';
+import { Preset, baseOptions } from './preset';
+import { constants, Env } from '../utils';
+
+export class DcUniversePreset extends Preset {
+ // dc-batman-animations%2C
+ // dc-superman-animations%2C
+ // dc-batman%2C
+ // dc-superman
+ private static catalogs = [
+ {
+ label: 'DC Chronological Order',
+ value: 'dc-chronological',
+ },
+ {
+ label: 'DC Release Order',
+ value: 'dc-release',
+ },
+ {
+ label: 'Movies',
+ value: 'dc-movies',
+ },
+ {
+ label: 'DCEU Movies',
+ value: 'dceu_movies',
+ },
+ {
+ label: 'Series',
+ value: 'dc-series',
+ },
+ {
+ label: 'DC Modern Series',
+ value: 'dc_modern_series',
+ },
+ {
+ label: 'Animations',
+ value: 'dc-animations',
+ },
+ {
+ label: 'Batman Animations',
+ value: 'dc-batman-animations',
+ },
+ {
+ label: 'Superman Animations',
+ value: 'dc-superman-animations',
+ },
+ {
+ label: 'Batman Collection',
+ value: 'dc-batman',
+ },
+ {
+ label: 'Superman Collection',
+ value: 'dc-superman',
+ },
+ ];
+ static override get METADATA() {
+ const supportedResources = [
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ ];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'DC Universe',
+ supportedResources,
+ Env.DEFAULT_DC_UNIVERSE_TIMEOUT
+ ).filter((option) => option.id !== 'url'),
+ // series movies animations xmen release-order marvel-mcu
+ {
+ id: 'catalogs',
+ name: 'Catalogs',
+ description: 'The catalogs to display',
+ type: 'multi-select',
+ required: true,
+ options: this.catalogs,
+ default: this.catalogs.map((catalog) => catalog.value),
+ },
+ ];
+
+ return {
+ ID: 'dc-universe',
+ NAME: 'DC Universe',
+ LOGO: 'https://raw.githubusercontent.com/tapframe/addon-dc/refs/heads/main/assets/icon.png',
+ URL: Env.DC_UNIVERSE_URL,
+ TIMEOUT: Env.DEFAULT_DC_UNIVERSE_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_DC_UNIVERSE_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION:
+ 'Explore the DC Universe by release date, movies, series, and animations!',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ const config =
+ options.catalogs.length !== this.catalogs.length
+ ? options.catalogs.join('%2C')
+ : '';
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: `${Env.DC_UNIVERSE_URL}/${config ? 'catalog/' + config + '/' : ''}manifest.json`,
+ enabled: true,
+ library: false,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/debridio.ts b/packages/core/src/presets/debridio.ts
new file mode 100644
index 00000000..00805cb1
--- /dev/null
+++ b/packages/core/src/presets/debridio.ts
@@ -0,0 +1,131 @@
+import { Addon, Option, UserData, Resource, Stream } from '../db';
+import { Preset, baseOptions } from './preset';
+import { Env, SERVICE_DETAILS } from '../utils';
+import { constants, ServiceId } from '../utils';
+import { StreamParser } from '../parser';
+
+export class DebridioPreset extends Preset {
+ static override get METADATA() {
+ const supportedServices: ServiceId[] = [constants.EASYDEBRID_SERVICE];
+ const supportedResources = [constants.STREAM_RESOURCE];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'Debridio',
+ supportedResources,
+ Env.DEFAULT_DEBRIDIO_TIMEOUT
+ ),
+ // {
+ // id: 'services',
+ // name: 'Services',
+ // description:
+ // 'Optionally override the services that are used. If not specified, then the services that are enabled and supported will be used.',
+ // type: 'multi-select',
+ // required: false,
+ // options: supportedServices.map((service) => ({
+ // value: service,
+ // label: constants.SERVICE_DETAILS[service].name,
+ // })),
+ // default: undefined,
+ // emptyIsUndefined: true,
+ // },
+ // {
+ // id: 'useMultipleInstances',
+ // name: 'Use Multiple Instances',
+ // description:
+ // 'When using multiple services, use a different Torrentio addon for each service, rather than using one instance for all services',
+ // type: 'boolean',
+ // default: false,
+ // required: true,
+ // },
+ ];
+
+ return {
+ ID: 'debridio',
+ NAME: 'Debridio',
+ LOGO: 'https://res.cloudinary.com/adobotec/image/upload/w_120,h_120/v1735925306/debridio/logo.png.png',
+ URL: Env.DEBRIDIO_URL,
+ TIMEOUT: Env.DEFAULT_DEBRIDIO_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_DEBRIDIO_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: supportedServices,
+ DESCRIPTION: 'Torrent streaming using Debrid providers.',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [constants.DEBRID_STREAM_TYPE],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ if (options?.url?.endsWith('/manifest.json')) {
+ return [this.generateAddon(userData, options, undefined)];
+ }
+
+ const usableServices = this.getUsableServices(userData);
+
+ // if no services are usable, return a single addon with no services
+ if (!usableServices || usableServices.length === 0) {
+ throw new Error(
+ `${this.METADATA.NAME} requires at least one of the following services to be enabled: ${this.METADATA.SUPPORTED_SERVICES.join(
+ ', '
+ )}`
+ );
+ }
+
+ return usableServices.map((service) =>
+ this.generateAddon(userData, options, service.id)
+ );
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record,
+ service?: ServiceId
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: service
+ ? `${options.name || this.METADATA.NAME} ${constants.SERVICE_DETAILS[service].shortName}`
+ : options.name || this.METADATA.NAME,
+ manifestUrl: this.generateManifestUrl(userData, service, options.url),
+ enabled: true,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+
+ private static generateManifestUrl(
+ userData: UserData,
+ service?: ServiceId,
+ url?: string
+ ) {
+ url = url || this.METADATA.URL;
+ if (url.endsWith('/manifest.json')) {
+ return url;
+ }
+ if (!service) {
+ throw new Error(
+ `${this.METADATA.NAME} requires at least one of the following services to be enabled: ${this.METADATA.SUPPORTED_SERVICES.join(
+ ', '
+ )}`
+ );
+ }
+
+ const configString = this.base64EncodeJSON({
+ provider: service,
+ apiKey: this.getServiceCredential(service, userData),
+ disableUncached: false,
+ qualityOrder: [],
+ excludeSize: '',
+ maxReturnPerQuality: '',
+ });
+
+ return `${url}${configString ? '/' + configString : ''}/manifest.json`;
+ }
+}
diff --git a/packages/core/src/presets/debridioTmdb.ts b/packages/core/src/presets/debridioTmdb.ts
new file mode 100644
index 00000000..2bb0a89b
--- /dev/null
+++ b/packages/core/src/presets/debridioTmdb.ts
@@ -0,0 +1,143 @@
+import { Addon, Option, UserData } from '../db';
+import { Preset, baseOptions } from './preset';
+import { constants, Env, FULL_LANGUAGE_MAPPING } from '../utils';
+
+export class DebridioTmdbPreset extends Preset {
+ static override get METADATA() {
+ const supportedResources = [
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ ];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'Debridio TMDB',
+ supportedResources,
+ Env.DEFAULT_DEBRIDIO_TMDB_TIMEOUT
+ ),
+ {
+ id: 'debridioApiKey',
+ name: 'Debridio API Key',
+ description:
+ 'Your Debridio API Key, located at your [account settings](https://debridio.com/account)',
+ type: 'password',
+ required: true,
+ },
+ {
+ id: 'language',
+ name: 'Language',
+ description: 'The language of the catalogs',
+ type: 'select',
+ default: 'en-US',
+ options: FULL_LANGUAGE_MAPPING.sort((a, b) =>
+ a.english_name.localeCompare(b.english_name)
+ ).map((language) => ({
+ label: language.english_name,
+ value: `${language.iso_639_1}-${language.iso_3166_1}`,
+ })),
+ required: false,
+ },
+ ];
+
+ return {
+ ID: 'debridio-tmdb',
+ NAME: 'Debridio TMDB',
+ LOGO: 'https://res.cloudinary.com/adobotec/image/upload/w_120,h_120/v1735925306/debridio/logo.png.png',
+ URL: Env.DEBRIDIO_TMDB_URL,
+ TIMEOUT: Env.DEFAULT_DEBRIDIO_TMDB_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT:
+ Env.DEFAULT_DEBRIDIO_TMDB_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION: 'Catalogs for the Debridio TMDB',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ if (!options.debridioApiKey && !options.url) {
+ throw new Error(
+ 'To access the Debridio addons, you must provide your Debridio API Key'
+ );
+ }
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ let url = this.METADATA.URL;
+ if (options.url?.endsWith('/manifest.json')) {
+ url = options.url;
+ } else {
+ let baseUrl = this.METADATA.URL;
+ if (options.url) {
+ baseUrl = new URL(options.url).origin;
+ }
+ // remove trailing slash
+ baseUrl = baseUrl.replace(/\/$/, '');
+ if (!options.debridioApiKey) {
+ throw new Error(
+ 'To access the Debridio addons, you must provide your Debridio API Key'
+ );
+ }
+ const config = this.base64EncodeJSON({
+ api_key: options.debridioApiKey,
+ language: options.language || 'en-US',
+ rpdb_api: '',
+ catalogs: [
+ {
+ id: 'debridio_tmdb.movie_trending',
+ home: true,
+ enabled: true,
+ name: 'Trending',
+ },
+ {
+ id: 'debridio_tmdb.movie_popular',
+ home: true,
+ enabled: true,
+ name: 'Popular',
+ },
+ {
+ id: 'debridio_tmdb.tv_trending',
+ home: true,
+ enabled: true,
+ name: 'Trending',
+ },
+ {
+ id: 'debridio_tmdb.tv_popular',
+ home: true,
+ enabled: true,
+ name: 'Popular',
+ },
+ {
+ id: 'debridio_tmdb.search_collections',
+ home: false,
+ enabled: true,
+ name: 'Search',
+ },
+ ],
+ });
+ url = `${baseUrl}/${config}/manifest.json`;
+ }
+
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: url,
+ enabled: true,
+ library: false,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/debridioTv.ts b/packages/core/src/presets/debridioTv.ts
new file mode 100644
index 00000000..f862a0ef
--- /dev/null
+++ b/packages/core/src/presets/debridioTv.ts
@@ -0,0 +1,126 @@
+import { Addon, Option, UserData } from '../db';
+import { Preset, baseOptions } from './preset';
+import { constants, Env } from '../utils';
+
+export class DebridioTvPreset extends Preset {
+ static override get METADATA() {
+ const supportedResources = [
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ constants.STREAM_RESOURCE,
+ ];
+
+ const channels = [
+ {
+ label: 'USA',
+ value: 'usa',
+ },
+ {
+ label: 'Mexico',
+ value: 'mx',
+ },
+ {
+ label: 'UK',
+ value: 'uk',
+ },
+ {
+ label: 'Chile',
+ value: 'cl',
+ },
+ {
+ label: 'Estonia',
+ value: 'ee',
+ },
+ ];
+ const options: Option[] = [
+ ...baseOptions(
+ 'Debridio TV',
+ supportedResources,
+ Env.DEFAULT_DEBRIDIO_TV_TIMEOUT
+ ),
+ {
+ id: 'debridioApiKey',
+ name: 'Debridio API Key',
+ description:
+ 'Your Debridio API Key, located at your [account settings](https://debridio.com/account)',
+ type: 'password',
+ required: true,
+ },
+ {
+ id: 'channels',
+ name: 'Channels',
+ description: 'The channels to display',
+ type: 'multi-select',
+ required: true,
+ options: channels,
+ default: channels.map((channel) => channel.value),
+ },
+ ];
+
+ return {
+ ID: 'debridio-tv',
+ NAME: 'Debridio TV',
+ LOGO: 'https://res.cloudinary.com/adobotec/image/upload/w_120,h_120/v1735925306/debridio/logo.png.png',
+ URL: Env.DEBRIDIO_TV_URL,
+ TIMEOUT: Env.DEFAULT_DEBRIDIO_TV_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_DEBRIDIO_TV_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION: 'Live streaming of a wide variety of channels.',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [constants.LIVE_STREAM_TYPE],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ if (!options.url && !options.debridioApiKey) {
+ throw new Error(
+ 'To access the Debridio addons, you must provide your Debridio API Key'
+ );
+ }
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ let url = this.METADATA.URL;
+ if (options.url?.endsWith('/manifest.json')) {
+ url = options.url;
+ } else {
+ let baseUrl = this.METADATA.URL;
+ if (options.url) {
+ baseUrl = new URL(options.url).origin;
+ }
+ // remove trailing slash
+ baseUrl = baseUrl.replace(/\/$/, '');
+ if (!options.debridioApiKey) {
+ throw new Error(
+ 'To access the Debridio addons, you must provide your Debridio API Key'
+ );
+ }
+ const config = this.base64EncodeJSON({
+ api_key: options.debridioApiKey,
+ channels: options.channels,
+ });
+ url = `${baseUrl}/${config}/manifest.json`;
+ }
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: url,
+ enabled: true,
+ library: false,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/debridioTvdb.ts b/packages/core/src/presets/debridioTvdb.ts
new file mode 100644
index 00000000..113ddfac
--- /dev/null
+++ b/packages/core/src/presets/debridioTvdb.ts
@@ -0,0 +1,90 @@
+import { Addon, Option, UserData } from '../db';
+import { Preset, baseOptions } from './preset';
+import { constants, Env } from '../utils';
+
+export class DebridioTvdbPreset extends Preset {
+ static override get METADATA() {
+ const supportedResources = [
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ ];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'Debridio TVDB',
+ supportedResources,
+ Env.DEFAULT_DEBRIDIO_TVDB_TIMEOUT
+ ),
+ {
+ id: 'debridioApiKey',
+ name: 'Debridio API Key',
+ description:
+ 'Your Debridio API Key, located at your [account settings](https://debridio.com/account)',
+ type: 'password',
+ required: true,
+ },
+ ];
+
+ return {
+ ID: 'debridio-tvdb',
+ NAME: 'Debridio TVDB',
+ LOGO: 'https://res.cloudinary.com/adobotec/image/upload/w_120,h_120/v1735925306/debridio/logo.png.png',
+ URL: Env.DEBRIDIO_TVDB_URL,
+ TIMEOUT: Env.DEFAULT_DEBRIDIO_TVDB_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT:
+ Env.DEFAULT_DEBRIDIO_TVDB_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION: 'Catalogs for the Debridio TVDB',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ if (!options.url && !options.debridioApiKey) {
+ throw new Error(
+ 'To access the Debridio addons, you must provide your Debridio API Key'
+ );
+ }
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ let url = this.METADATA.URL;
+ if (options.url?.endsWith('/manifest.json')) {
+ url = options.url;
+ } else {
+ let baseUrl = this.METADATA.URL;
+ if (options.url) {
+ baseUrl = new URL(options.url).origin;
+ }
+ // remove trailing slash
+ baseUrl = baseUrl.replace(/\/$/, '');
+ const config = this.base64EncodeJSON({
+ api_key: options.debridioApiKey,
+ language: 'eng',
+ });
+ url = `${baseUrl}/${config}/manifest.json`;
+ }
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: url,
+ enabled: true,
+ library: false,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/debridioWatchtower.ts b/packages/core/src/presets/debridioWatchtower.ts
new file mode 100644
index 00000000..f28a08d8
--- /dev/null
+++ b/packages/core/src/presets/debridioWatchtower.ts
@@ -0,0 +1,158 @@
+import { Addon, Option, ParsedStream, Stream, UserData } from '../db';
+import { Preset, baseOptions } from './preset';
+import { constants, Env } from '../utils';
+import { FileParser, StreamParser } from '../parser';
+
+class DebridioWatchtowerStreamParser extends StreamParser {
+ parse(stream: Stream): ParsedStream {
+ let parsedStream: ParsedStream = {
+ addon: this.addon,
+ type: 'http',
+ url: this.applyUrlModifications(stream.url),
+ externalUrl: stream.externalUrl,
+ ytId: stream.ytId,
+ requestHeaders: stream.behaviorHints?.proxyHeaders?.request,
+ responseHeaders: stream.behaviorHints?.proxyHeaders?.response,
+ notWebReady: stream.behaviorHints?.notWebReady,
+ videoHash: stream.behaviorHints?.videoHash,
+ originalName: stream.name,
+ originalDescription: stream.description || stream.title,
+ };
+
+ stream.description = stream.description || stream.title;
+
+ parsedStream.filename = this.getFilename(stream, parsedStream);
+
+ parsedStream.type = this.getStreamType(
+ stream,
+ parsedStream.service,
+ parsedStream
+ );
+
+ if (parsedStream.filename) {
+ parsedStream.parsedFile = FileParser.parse(parsedStream.filename);
+ parsedStream.parsedFile = {
+ resolution: parsedStream.parsedFile.resolution,
+ languages: [],
+ audioChannels: [],
+ visualTags: [],
+ audioTags: [],
+ };
+ parsedStream.parsedFile.languages = Array.from(
+ new Set([
+ ...parsedStream.parsedFile.languages,
+ ...this.getLanguages(stream, parsedStream),
+ ])
+ );
+ }
+
+ parsedStream.filename = undefined;
+ parsedStream.folderName = undefined;
+
+ parsedStream.message = stream.description?.replace(/\d+p?/g, '');
+
+ parsedStream.torrent = {
+ infoHash:
+ parsedStream.type === 'p2p'
+ ? stream.infoHash
+ : this.getInfoHash(stream, parsedStream),
+ seeders: this.getSeeders(stream, parsedStream),
+ sources: stream.sources,
+ fileIdx: stream.fileIdx,
+ };
+
+ return parsedStream;
+ }
+}
+
+export class DebridioWatchtowerPreset extends Preset {
+ static override getParser(): typeof StreamParser {
+ return DebridioWatchtowerStreamParser;
+ }
+
+ static override get METADATA() {
+ const supportedResources = [constants.STREAM_RESOURCE];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'Debridio Watchtower',
+ supportedResources,
+ Env.DEFAULT_DEBRIDIO_WATCHTOWER_TIMEOUT
+ ),
+ {
+ id: 'debridioApiKey',
+ name: 'Debridio API Key',
+ description:
+ 'Your Debridio API Key, located at your [account settings](https://debridio.com/account)',
+ type: 'password',
+ required: true,
+ },
+ ];
+
+ return {
+ ID: 'debridio-watchtower',
+ NAME: 'Debridio Watchtower',
+ LOGO: 'https://res.cloudinary.com/adobotec/image/upload/w_120,h_120/v1735925306/debridio/logo.png.png',
+ URL: Env.DEBRIDIO_WATCHTOWER_URL,
+ TIMEOUT: Env.DEFAULT_DEBRIDIO_WATCHTOWER_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT:
+ Env.DEFAULT_DEBRIDIO_WATCHTOWER_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION: 'Watchtower is a http stream provider.',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [constants.HTTP_STREAM_TYPE],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ if (!options.url && !options.debridioApiKey) {
+ throw new Error(
+ 'To access the Debridio addons, you must provide your Debridio API Key'
+ );
+ }
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ let url = this.METADATA.URL;
+ if (options.url?.endsWith('/manifest.json')) {
+ url = options.url;
+ } else {
+ let baseUrl = this.METADATA.URL;
+ if (options.url) {
+ baseUrl = new URL(options.url).origin;
+ }
+ // remove trailing slash
+ baseUrl = baseUrl.replace(/\/$/, '');
+ if (!options.debridioApiKey) {
+ throw new Error(
+ 'To access the Debridio addons, you must provide your Debridio API Key'
+ );
+ }
+ const config = this.base64EncodeJSON({
+ api_key: options.debridioApiKey,
+ });
+ url = `${baseUrl}/${config}/manifest.json`;
+ }
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: url,
+ enabled: true,
+ library: false,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/dmmCast.ts b/packages/core/src/presets/dmmCast.ts
new file mode 100644
index 00000000..10c1dac2
--- /dev/null
+++ b/packages/core/src/presets/dmmCast.ts
@@ -0,0 +1,144 @@
+import {
+ Addon,
+ Option,
+ UserData,
+ ParsedStream,
+ Stream,
+ AIOStream,
+} from '../db';
+import { Preset, baseOptions } from './preset';
+import { constants, Env, RESOURCES } from '../utils';
+import { StreamParser } from '../parser';
+
+class DMMCastStreamParser extends StreamParser {
+ protected override getFilename(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ let filename = stream.description
+ ? stream.description
+ .split('\n')
+ .map((line) => line.replace(/-$/, ''))
+ .filter((line) => !line.includes('📦'))
+ .join('')
+ : stream.behaviorHints?.filename?.trim();
+ return filename;
+ }
+
+ protected override getMessage(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ if (!stream.description?.includes('📦')) {
+ currentParsedStream.filename = undefined;
+ return `${stream.name} - ${stream.description}`;
+ }
+ return undefined;
+ }
+
+ protected override getInLibrary(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): boolean {
+ if (stream.name?.includes('Yours')) {
+ return true;
+ }
+ return false;
+ }
+}
+
+export class DMMCastPreset extends Preset {
+ static override getParser(): typeof StreamParser {
+ return DMMCastStreamParser;
+ }
+
+ static override get METADATA() {
+ const supportedResources = [constants.STREAM_RESOURCE];
+ const options: Option[] = [
+ {
+ id: 'name',
+ name: 'Name',
+ description: 'What to call this addon',
+ type: 'string',
+ required: true,
+ default: 'DMM Cast',
+ },
+ {
+ id: 'installationUrl',
+ name: 'Installation URL',
+ description:
+ 'Provide the Unique Installation URL for your DMM Cast addon, available [here](https://debridmediamanager.com/stremio)',
+ type: 'url',
+ required: true,
+ },
+ {
+ id: 'timeout',
+ name: 'Timeout',
+ description: 'The timeout for this addon',
+ type: 'number',
+ default: Env.DEFAULT_DMM_CAST_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ constraints: {
+ min: Env.MIN_TIMEOUT,
+ max: Env.MAX_TIMEOUT,
+ },
+ },
+ {
+ id: 'resources',
+ name: 'Resources',
+ description:
+ 'Optionally override the resources that are fetched from this addon ',
+ type: 'multi-select',
+ required: false,
+ default: undefined,
+ options: RESOURCES.map((resource) => ({
+ label: resource,
+ value: resource,
+ })),
+ },
+ ];
+
+ return {
+ ID: 'dmm-cast',
+ NAME: 'DMM Cast',
+ LOGO: 'https://static.debridmediamanager.com/dmmcast.png',
+ URL: '',
+ TIMEOUT: Env.DEFAULT_DMM_CAST_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_DMM_CAST_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION:
+ 'Access streams casted from [DMM](https://debridmediamanager.com) by you or other users',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ if (!options.installationUrl.endsWith('/manifest.json')) {
+ throw new Error('Invalid installation URL');
+ }
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: options.installationUrl,
+ enabled: true,
+ library: false,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/easynews.ts b/packages/core/src/presets/easynews.ts
new file mode 100644
index 00000000..bf2b958c
--- /dev/null
+++ b/packages/core/src/presets/easynews.ts
@@ -0,0 +1,120 @@
+import { baseOptions, Preset } from './preset';
+import { constants, Env } from '../utils';
+import {
+ PresetMetadata,
+ Option,
+ Addon,
+ UserData,
+ ParsedStream,
+ Stream,
+} from '../db';
+import { StreamParser } from '../parser';
+
+export class EasynewsParser extends StreamParser {
+ protected override getStreamType(
+ stream: Stream,
+ service: ParsedStream['service'],
+ currentParsedStream: ParsedStream
+ ): ParsedStream['type'] {
+ return constants.USENET_STREAM_TYPE;
+ }
+}
+
+export class EasynewsPreset extends Preset {
+ static override getParser(): typeof StreamParser {
+ return EasynewsParser;
+ }
+
+ static override get METADATA(): PresetMetadata {
+ const supportedServices = [constants.EASYNEWS_SERVICE];
+ const supportedResources = [constants.STREAM_RESOURCE];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'Easynews',
+ supportedResources,
+ Env.DEFAULT_EASYNEWS_TIMEOUT
+ ),
+ ];
+
+ return {
+ ID: 'easynews',
+ NAME: 'Easynews',
+ DESCRIPTION:
+ 'The original Easynews addon, to access streams from Easynews',
+ LOGO: `https://pbs.twimg.com/profile_images/479627852757733376/8v9zH7Yo_400x400.jpeg`,
+ URL: Env.EASYNEWS_URL,
+ TIMEOUT: Env.DEFAULT_EASYNEWS_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_EASYNEWS_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: supportedServices,
+ SUPPORTED_RESOURCES: supportedResources,
+ SUPPORTED_STREAM_TYPES: [constants.USENET_STREAM_TYPE],
+ OPTIONS: options,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: this.generateManifestUrl(userData, options),
+ enabled: true,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+
+ protected static generateConfig(
+ easynewsCredentials: {
+ username: string;
+ password: string;
+ },
+ options: Record
+ ) {
+ return this.urlEncodeJSON({
+ username: easynewsCredentials.username,
+ password: easynewsCredentials.password,
+ });
+ }
+
+ private static generateManifestUrl(
+ userData: UserData,
+ options: Record
+ ) {
+ let url = options.url || this.METADATA.URL;
+ if (url.endsWith('/manifest.json')) {
+ return url;
+ }
+ url = url.replace(/\/$/, '');
+ const easynewsCredentials = this.getServiceCredential(
+ constants.EASYNEWS_SERVICE,
+ userData,
+ {
+ [constants.EASYNEWS_SERVICE]: (credentials: any) => ({
+ username: credentials.username,
+ password: credentials.password,
+ }),
+ }
+ );
+ if (!easynewsCredentials) {
+ throw new Error(
+ `${this.METADATA.NAME} requires the Easynews service to be enabled.`
+ );
+ }
+ return `${url}/${this.generateConfig(easynewsCredentials, options)}/manifest.json`;
+ }
+}
diff --git a/packages/core/src/presets/easynewsPlus.ts b/packages/core/src/presets/easynewsPlus.ts
new file mode 100644
index 00000000..89c5ec54
--- /dev/null
+++ b/packages/core/src/presets/easynewsPlus.ts
@@ -0,0 +1,55 @@
+import { PresetMetadata } from '../db';
+import { EasynewsPreset } from './easynews';
+import { constants, Env } from '../utils';
+import { baseOptions } from './preset';
+
+export class EasynewsPlusPreset extends EasynewsPreset {
+ static override get METADATA(): PresetMetadata {
+ return {
+ ...super.METADATA,
+ ID: 'easynewsPlus',
+ NAME: 'Easynews+',
+ DESCRIPTION:
+ 'Easynews+ provides content from Easynews & includes a search catalog',
+ URL: Env.EASYNEWS_PLUS_URL,
+ TIMEOUT: Env.DEFAULT_EASYNEWS_PLUS_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT:
+ Env.DEFAULT_EASYNEWS_PLUS_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_RESOURCES: [
+ ...super.METADATA.SUPPORTED_RESOURCES,
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ ],
+ OPTIONS: [
+ ...baseOptions(
+ 'Easynews+',
+ [
+ ...super.METADATA.SUPPORTED_RESOURCES,
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ ],
+ Env.DEFAULT_EASYNEWS_PLUS_TIMEOUT || Env.DEFAULT_TIMEOUT
+ ),
+ ],
+ };
+ }
+
+ protected static override generateConfig(
+ easynewsCredentials: {
+ username: string;
+ password: string;
+ },
+ options: Record
+ ): string {
+ return this.urlEncodeJSON({
+ username: easynewsCredentials.username,
+ password: easynewsCredentials.password,
+ sort1: 'Size',
+ sort1Direction: 'Descending',
+ sort2: 'Relevance',
+ sort2Direction: 'Descending',
+ sort3: 'Date & Time',
+ sort3Direction: 'Descending',
+ });
+ }
+}
diff --git a/packages/core/src/presets/easynewsPlusPlus.ts b/packages/core/src/presets/easynewsPlusPlus.ts
new file mode 100644
index 00000000..ecf2d298
--- /dev/null
+++ b/packages/core/src/presets/easynewsPlusPlus.ts
@@ -0,0 +1,87 @@
+import { ParsedStream, PresetMetadata, Stream } from '../db';
+import { EasynewsPreset, EasynewsParser } from './easynews';
+import { constants, Env } from '../utils';
+import { baseOptions } from './preset';
+import { StreamParser } from '../parser';
+
+class EasynewsPlusPlusParser extends EasynewsParser {
+ protected override get ageRegex(): RegExp {
+ return /📅\s*(\d+[a-zA-Z])/;
+ }
+
+ protected get indexerRegex(): RegExp | undefined {
+ return undefined;
+ }
+
+ protected override getLanguages(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string[] {
+ const regex = this.getRegexForTextAfterEmojis(['🌐']);
+ const langs = stream.description?.match(regex)?.[1];
+ return (
+ langs
+ ?.split(',')
+ ?.map((lang) => this.convertISO6392ToLanguage(lang.trim()))
+ .filter((lang) => lang !== undefined) || []
+ );
+ }
+}
+
+export class EasynewsPlusPlusPreset extends EasynewsPreset {
+ static override getParser(): typeof StreamParser {
+ return EasynewsPlusPlusParser;
+ }
+
+ static override get METADATA(): PresetMetadata {
+ return {
+ ...super.METADATA,
+ ID: 'easynewsPlusPlus',
+ NAME: 'Easynews++',
+ DESCRIPTION: 'Easynews++ provides content from Easynews',
+ URL: Env.EASYNEWS_PLUS_PLUS_URL,
+ TIMEOUT: Env.DEFAULT_EASYNEWS_PLUS_PLUS_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT:
+ Env.DEFAULT_EASYNEWS_PLUS_PLUS_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ OPTIONS: [
+ ...baseOptions(
+ 'Easynews++',
+ super.METADATA.SUPPORTED_RESOURCES,
+ Env.DEFAULT_EASYNEWS_PLUS_PLUS_TIMEOUT || Env.DEFAULT_TIMEOUT
+ ),
+ {
+ id: 'strictTitleMatching',
+ name: 'Strict Title Matching',
+ description:
+ "Whether to filter out results that don't match the title exactly",
+ type: 'boolean',
+ required: true,
+ default: false,
+ },
+ ],
+ };
+ }
+
+ protected static override generateConfig(
+ easynewsCredentials: {
+ username: string;
+ password: string;
+ },
+ options: Record
+ ): string {
+ return this.urlEncodeJSON({
+ uiLanguage: 'eng',
+ username: easynewsCredentials.username,
+ password: easynewsCredentials.password,
+ strictTitleMatching: options.strictTitleMatching ? 'on' : 'off',
+ baseUrl: options.url
+ ? new URL(options.url).origin
+ : Env.EASYNEWS_PLUS_PLUS_URL,
+ preferredLanguage: '',
+ sortingPreference: 'quality_first',
+ showQualities: '4k,1080p,720p,480p',
+ maxResultsPerQuality: '',
+ maxFileSize: '',
+ });
+ }
+}
diff --git a/packages/core/src/presets/index.ts b/packages/core/src/presets/index.ts
new file mode 100644
index 00000000..e41c246d
--- /dev/null
+++ b/packages/core/src/presets/index.ts
@@ -0,0 +1,2 @@
+export * from './preset';
+export * from './presetManager';
diff --git a/packages/core/src/presets/jackettio.ts b/packages/core/src/presets/jackettio.ts
new file mode 100644
index 00000000..bc111ebc
--- /dev/null
+++ b/packages/core/src/presets/jackettio.ts
@@ -0,0 +1,183 @@
+import { Addon, Option, UserData, Resource } from '../db';
+import { baseOptions, Preset } from './preset';
+import { Env } from '../utils';
+import { constants, ServiceId } from '../utils';
+import { StreamParser } from '../parser';
+
+class JackettioStreamParser extends StreamParser {
+ override applyUrlModifications(url: string | undefined): string | undefined {
+ if (!url) {
+ return url;
+ }
+ if (
+ Env.FORCE_JACKETTIO_HOSTNAME !== undefined ||
+ Env.FORCE_JACKETTIO_PORT !== undefined ||
+ Env.FORCE_JACKETTIO_PROTOCOL !== undefined
+ ) {
+ // modify the URL according to settings, needed when using a local URL for requests but a public stream URL is needed.
+ const urlObj = new URL(url);
+
+ if (Env.FORCE_JACKETTIO_PROTOCOL !== undefined) {
+ urlObj.protocol = Env.FORCE_JACKETTIO_PROTOCOL;
+ }
+ if (Env.FORCE_JACKETTIO_PORT !== undefined) {
+ urlObj.port = Env.FORCE_JACKETTIO_PORT.toString();
+ }
+ if (Env.FORCE_JACKETTIO_HOSTNAME !== undefined) {
+ urlObj.hostname = Env.FORCE_JACKETTIO_HOSTNAME;
+ }
+ return urlObj.toString();
+ }
+ return url;
+ }
+}
+
+export class JackettioPreset extends Preset {
+ static override getParser(): typeof StreamParser {
+ return JackettioStreamParser;
+ }
+
+ static override get METADATA() {
+ const supportedServices: ServiceId[] = [
+ constants.REALDEBRID_SERVICE,
+ constants.PREMIUMIZE_SERVICE,
+ constants.ALLEDEBRID_SERVICE,
+ constants.TORBOX_SERVICE,
+ constants.EASYDEBRID_SERVICE,
+ constants.DEBRIDLINK_SERVICE,
+ constants.OFFCLOUD_SERVICE,
+ constants.PIKPAK_SERVICE,
+ ];
+
+ const supportedResources = [constants.STREAM_RESOURCE];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'Jackettio',
+ supportedResources,
+ Env.DEFAULT_JACKETTIO_TIMEOUT
+ ),
+ {
+ id: 'services',
+ name: 'Services',
+ description:
+ 'Optionally override the services that are used. If not specified, then the services that are enabled and supported will be used.',
+ type: 'multi-select',
+ required: false,
+ options: supportedServices.map((service) => ({
+ value: service,
+ label: constants.SERVICE_DETAILS[service].name,
+ })),
+ default: undefined,
+ emptyIsUndefined: true,
+ },
+ ];
+
+ return {
+ ID: 'jackettio',
+ NAME: 'Jackettio',
+ LOGO: 'https://raw.githubusercontent.com/Jackett/Jackett/bbea5febd623f6e536e11aa1fa8d6674d8d4043f/src/Jackett.Common/Content/jacket_medium.png',
+ URL: Env.JACKETTIO_URL,
+ TIMEOUT: Env.DEFAULT_JACKETTIO_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_JACKETTIO_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: supportedServices,
+ DESCRIPTION:
+ 'Stremio addon that resolves streams using Jackett and Debrid',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [constants.DEBRID_STREAM_TYPE],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ if (options?.url?.endsWith('/manifest.json')) {
+ return [this.generateAddon(userData, options, undefined)];
+ }
+
+ const usableServices = this.getUsableServices(userData, options.services);
+ if (!usableServices || usableServices.length === 0) {
+ throw new Error(
+ `${this.METADATA.NAME} requires at least one usable service from the list of supported services: ${this.METADATA.SUPPORTED_SERVICES.map((service) => constants.SERVICE_DETAILS[service].name).join(', ')}`
+ );
+ }
+
+ let addons = usableServices.map((service) =>
+ this.generateAddon(userData, options, service.id)
+ );
+
+ return addons;
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record,
+ serviceId?: ServiceId
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: serviceId
+ ? `${options.name || this.METADATA.NAME} ${constants.SERVICE_DETAILS[serviceId].shortName}`
+ : options.name || this.METADATA.NAME,
+ manifestUrl: this.generateManifestUrl(userData, options, serviceId),
+ enabled: true,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+
+ private static generateManifestUrl(
+ userData: UserData,
+ options: Record,
+ serviceId: ServiceId | undefined
+ ) {
+ let url = options.url || this.METADATA.URL;
+ if (url.endsWith('/manifest.json')) {
+ return url;
+ }
+ if (!serviceId) {
+ throw new Error(
+ `${this.METADATA.NAME} requires at least one usable service from the list of supported services: ${this.METADATA.SUPPORTED_SERVICES.map((service) => constants.SERVICE_DETAILS[service].name).join(', ')}`
+ );
+ }
+ url = url.replace(/\/$/, '');
+ const configString = this.base64EncodeJSON({
+ maxTorrents: 30,
+ priotizePackTorrents: 2,
+ excludeKeywords: [],
+ debridId: serviceId,
+ debridApiKey: this.getServiceCredential(serviceId, userData, {
+ [constants.OFFCLOUD_SERVICE]: (credentials: any) =>
+ `${credentials.email}:${credentials.password}`,
+ [constants.PIKPAK_SERVICE]: (credentials: any) =>
+ `${credentials.email}:${credentials.password}`,
+ }),
+ hideUncached: false,
+ sortCached: [
+ ['quality', true],
+ ['size', true],
+ ],
+ sortUncached: [['seeders', true]],
+ forceCacheNextEpisode: false,
+ priotizeLanguages: [],
+ indexerTimeoutSec: 60,
+ metaLanguage: '',
+ enableMediaFlow: false,
+ mediaflowProxyUrl: '',
+ mediaflowApiPassword: '',
+ mediaflowPublicIp: '',
+ useStremThru: true,
+ stremthruUrl: Env.DEFAULT_JACKETTIO_STREMTHRU_URL,
+ qualities: [0, 360, 480, 720, 1080, 2160],
+ indexers: Env.DEFAULT_JACKETTIO_INDEXERS,
+ });
+
+ return `${url}${configString ? '/' + configString : ''}/manifest.json`;
+ }
+}
diff --git a/packages/core/src/presets/marvel.ts b/packages/core/src/presets/marvel.ts
new file mode 100644
index 00000000..83990e15
--- /dev/null
+++ b/packages/core/src/presets/marvel.ts
@@ -0,0 +1,101 @@
+import { Addon, Option, UserData } from '../db';
+import { Preset, baseOptions } from './preset';
+import { constants, Env } from '../utils';
+
+export class MarvelPreset extends Preset {
+ private static catalogs = [
+ {
+ label: 'MCU Chronological Order',
+ value: 'marvel-mcu',
+ },
+ {
+ label: 'MCU Release Order',
+ value: 'release-order',
+ },
+ {
+ label: 'X-Men Chronological Order',
+ value: 'xmen',
+ },
+ {
+ label: 'Marvel Movies',
+ value: 'movies',
+ },
+ {
+ label: 'Marvel TV Shows',
+ value: 'series',
+ },
+ {
+ label: 'Marvel Animated Series',
+ value: 'animations',
+ },
+ ];
+ static override get METADATA() {
+ const supportedResources = [
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ ];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'Marvel Universe',
+ supportedResources,
+ Env.DEFAULT_MARVEL_CATALOG_TIMEOUT
+ ).filter((option) => option.id !== 'url'),
+ // series movies animations xmen release-order marvel-mcu
+ {
+ id: 'catalogs',
+ name: 'Catalogs',
+ description: 'The catalogs to display',
+ type: 'multi-select',
+ required: true,
+ options: this.catalogs,
+ default: this.catalogs.map((catalog) => catalog.value),
+ },
+ ];
+
+ return {
+ ID: 'marvel-universe',
+ NAME: 'Marvel Universe',
+ LOGO: 'https://upload.wikimedia.org/wikipedia/commons/b/b9/Marvel_Logo.svg',
+ URL: Env.MARVEL_UNIVERSE_URL,
+ TIMEOUT: Env.DEFAULT_MARVEL_CATALOG_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT:
+ Env.DEFAULT_MARVEL_CATALOG_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION: 'Catalogs for the Marvel Universe',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ const config =
+ options.catalogs.length !== this.catalogs.length
+ ? options.catalogs.join('%2C')
+ : '';
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: `${Env.MARVEL_UNIVERSE_URL}/${config ? 'catalog/' + config + '/' : ''}manifest.json`,
+ enabled: true,
+ library: false,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/mediafusion.ts b/packages/core/src/presets/mediafusion.ts
new file mode 100644
index 00000000..539b1615
--- /dev/null
+++ b/packages/core/src/presets/mediafusion.ts
@@ -0,0 +1,424 @@
+import { Addon, Option, UserData, Resource, Stream, ParsedStream } from '../db';
+import { baseOptions, Preset } from './preset';
+import { createLogger, Env } from '../utils';
+import { constants, ServiceId } from '../utils';
+import { StreamParser } from '../parser';
+
+const logger = createLogger('core');
+
+class MediaFusionStreamParser extends StreamParser {
+ protected override raiseErrorIfNecessary(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): void {
+ if (stream.description?.includes('Content Warning')) {
+ throw new Error(stream.description);
+ }
+ }
+
+ protected override get indexerEmojis(): string[] {
+ return ['🔗'];
+ }
+
+ protected override getFolder(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ const regex = this.getRegexForTextAfterEmojis(['📂']);
+ const file = stream.description?.match(regex)?.[1];
+ if (file && file.includes('┈➤')) {
+ return file.split('┈➤')[0].trim();
+ }
+ return undefined;
+ }
+
+ protected override getFolderSize(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): number | undefined {
+ const regex = /💾\s?.*\s?\/\s?💾\s?([^💾\n]+)/;
+ const match = stream.description?.match(regex);
+ if (match) {
+ const folderSize = match[1].trim();
+ return this.calculateBytesFromSizeString(folderSize);
+ }
+ return undefined;
+ }
+
+ protected override getFilename(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ const regex = this.getRegexForTextAfterEmojis(['📂']);
+ const file = stream.description?.match(regex)?.[1];
+ if (file && file.includes('┈➤')) {
+ return file.split('┈➤')[1].trim();
+ }
+ return file?.trim();
+ }
+
+ protected override getIndexer(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ const indexer = super.getIndexer(stream, currentParsedStream);
+ if (indexer?.includes('Contribution')) {
+ const contributor = stream.description?.match(
+ this.getRegexForTextAfterEmojis(['🧑💻'])
+ )?.[1];
+ return contributor ? `Contributor|${contributor}` : undefined;
+ }
+ return indexer;
+ }
+
+ protected override getLanguages(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string[] {
+ const languages = super.getLanguages(stream, currentParsedStream);
+ const regex = this.getRegexForTextAfterEmojis(['🌐']);
+ const languagesString = stream.description?.match(regex)?.[1];
+ if (languagesString) {
+ return languages.concat(
+ languagesString
+ .split('+')
+ .map((language) => language.trim())
+ .filter((language) => constants.LANGUAGES.includes(language as any))
+ );
+ }
+ return languages;
+ }
+}
+
+export class MediaFusionPreset extends Preset {
+ static override getParser(): typeof StreamParser {
+ return MediaFusionStreamParser;
+ }
+
+ static override get METADATA() {
+ const supportedServices: ServiceId[] = [
+ constants.REALDEBRID_SERVICE,
+ constants.PREMIUMIZE_SERVICE,
+ constants.ALLEDEBRID_SERVICE,
+ constants.TORBOX_SERVICE,
+ constants.DEBRIDLINK_SERVICE,
+ constants.EASYDEBRID_SERVICE,
+ constants.OFFCLOUD_SERVICE,
+ constants.PIKPAK_SERVICE,
+ constants.SEEDR_SERVICE,
+ ];
+
+ const supportedResources = [constants.STREAM_RESOURCE];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'MediaFusion',
+ supportedResources,
+ Env.DEFAULT_MEDIAFUSION_TIMEOUT
+ ),
+ {
+ id: 'useCachedResultsOnly',
+ name: 'Use Cached Results Only',
+ description:
+ "Only show results that are already cached in MediaFusion's database from previous searches. This disables live searching, making requests faster but potentially showing fewer results.",
+ type: 'boolean',
+ default: true,
+ },
+ {
+ id: 'enableWatchlistCatalogs',
+ name: 'Enable Watchlist Catalogs',
+ description: 'Enable watchlist catalogs for the selected services.',
+ type: 'boolean',
+ default: false,
+ },
+ {
+ id: 'downloadViaBrowser',
+ name: 'Download via Browser',
+ description:
+ 'Show download streams to allow downloading the stream from your service, rather than streaming.',
+ type: 'boolean',
+ default: false,
+ },
+ {
+ id: 'certificationLevelsFilter',
+ name: 'Certification Levels Filter',
+ description:
+ 'Choose to not display streams for titles of a certain certification level. Leave blank to show all results.',
+ type: 'multi-select',
+ required: false,
+ options: [
+ {
+ value: 'Unknown',
+ label: 'Unknown',
+ },
+ {
+ value: 'All Ages',
+ label: 'All Ages',
+ },
+ {
+ value: 'Children',
+ label: 'Children',
+ },
+ {
+ value: 'Parental Guidance',
+ label: 'Parental Guidance',
+ },
+ {
+ value: 'Teen',
+ label: 'Teen',
+ },
+ {
+ value: 'Adults',
+ label: 'Adults',
+ },
+ {
+ value: 'Adults+',
+ label: 'Adults+',
+ },
+ ],
+ },
+ {
+ id: 'nudityFilter',
+ name: 'Nudity Filter',
+ description:
+ 'Choose to not display streams that a certain level of nudity. Leave blank to show all results.',
+ type: 'multi-select',
+ required: false,
+ options: [
+ {
+ value: 'Unknown',
+ label: 'Unknown',
+ },
+ {
+ value: 'None',
+ label: 'None',
+ },
+ {
+ value: 'Mild',
+ label: 'Mild',
+ },
+ {
+ value: 'Moderate',
+ label: 'Moderate',
+ },
+ {
+ value: 'Severe',
+ label: 'Severe',
+ },
+ ],
+ },
+
+ {
+ id: 'services',
+ name: 'Services',
+ description:
+ 'Optionally override the services that are used. If not specified, then the services that are enabled and supported will be used.',
+ type: 'multi-select',
+ required: false,
+ options: supportedServices.map((service) => ({
+ value: service,
+ label: constants.SERVICE_DETAILS[service].name,
+ })),
+ default: undefined,
+ emptyIsUndefined: true,
+ },
+ ];
+
+ return {
+ ID: 'mediafusion',
+ NAME: 'MediaFusion',
+ LOGO: `https://raw.githubusercontent.com/mhdzumair/MediaFusion/refs/heads/main/resources/images/mediafusion_logo.png`,
+ URL: Env.MEDIAFUSION_URL,
+ TIMEOUT: Env.DEFAULT_MEDIAFUSION_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_MEDIAFUSION_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: supportedServices,
+ DESCRIPTION:
+ 'Universal Stremio Add-on for Movies, Series, Live TV & Sports Events',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [
+ constants.P2P_STREAM_TYPE,
+ constants.DEBRID_STREAM_TYPE,
+ ],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ if (options?.url?.endsWith('/manifest.json')) {
+ return [this.generateAddon(userData, options, undefined)];
+ }
+
+ const usableServices = this.getUsableServices(userData, options.services);
+
+ if (!usableServices || usableServices.length === 0) {
+ return [this.generateAddon(userData, options, undefined)];
+ }
+
+ let addons = usableServices.map((service) =>
+ this.generateAddon(userData, options, service.id)
+ );
+
+ if (options.includeP2P) {
+ addons.push(this.generateAddon(userData, options, undefined));
+ }
+
+ return addons;
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record,
+ serviceId?: ServiceId
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: serviceId
+ ? `${options.name || this.METADATA.NAME} ${constants.SERVICE_DETAILS[serviceId].shortName}`
+ : options.name || this.METADATA.NAME,
+ manifestUrl: `${Env.MEDIAFUSION_URL}/manifest.json`,
+ enabled: true,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ encoded_user_data: this.generateEncodedUserData(
+ userData,
+ options,
+ serviceId
+ ),
+ },
+ };
+ }
+
+ private static generateEncodedUserData(
+ userData: UserData,
+ options: Record,
+ serviceId: ServiceId | undefined
+ ) {
+ let url = options.url || this.METADATA.URL;
+ if (url.endsWith('/manifest.json')) {
+ return url;
+ }
+ url = url.replace(/\/$/, '');
+ const encodedUserData = this.base64EncodeJSON(
+ {
+ streaming_provider: !serviceId
+ ? null
+ : {
+ token: this.getServiceCredential(serviceId, userData),
+ service: serviceId,
+ enable_watchlist_catalogs:
+ options.enableWatchlistCatalogs || false,
+ download_via_browser: options.downloadViaBrowser || false,
+ only_show_cached_streams: false,
+ },
+ selected_catalogs: [],
+ selected_resolutions: [
+ '4k',
+ '2160p',
+ '1440p',
+ '1080p',
+ '720p',
+ '576p',
+ '480p',
+ '360p',
+ '240p',
+ null,
+ ],
+ enable_catalogs: true,
+ enable_imdb_metadata: false,
+ max_size: 'inf',
+ max_streams_per_resolution: '10',
+ torrent_sorting_priority: [
+ { key: 'language', direction: 'desc' },
+ { key: 'cached', direction: 'desc' },
+ { key: 'resolution', direction: 'desc' },
+ { key: 'quality', direction: 'desc' },
+ { key: 'size', direction: 'desc' },
+ { key: 'seeders', direction: 'desc' },
+ { key: 'created_at', direction: 'desc' },
+ ],
+ show_full_torrent_name: true,
+ show_language_country_flag: false,
+ nudity_filter: options.nudityFilter?.length
+ ? options.nudityFilter
+ : ['Disable'],
+ certification_filter: options.certificationLevelsFilter?.length
+ ? options.certificationLevelsFilter
+ : ['Disable'],
+ language_sorting: [
+ 'English',
+ 'Tamil',
+ 'Hindi',
+ 'Malayalam',
+ 'Kannada',
+ 'Telugu',
+ 'Chinese',
+ 'Russian',
+ 'Arabic',
+ 'Japanese',
+ 'Korean',
+ 'Taiwanese',
+ 'Latino',
+ 'French',
+ 'Spanish',
+ 'Portuguese',
+ 'Italian',
+ 'German',
+ 'Ukrainian',
+ 'Polish',
+ 'Czech',
+ 'Thai',
+ 'Indonesian',
+ 'Vietnamese',
+ 'Dutch',
+ 'Bengali',
+ 'Turkish',
+ 'Greek',
+ 'Swedish',
+ 'Romanian',
+ 'Hungarian',
+ 'Finnish',
+ 'Norwegian',
+ 'Danish',
+ 'Hebrew',
+ 'Lithuanian',
+ 'Punjabi',
+ 'Marathi',
+ 'Gujarati',
+ 'Bhojpuri',
+ 'Nepali',
+ 'Urdu',
+ 'Tagalog',
+ 'Filipino',
+ 'Malay',
+ 'Mongolian',
+ 'Armenian',
+ 'Georgian',
+ null,
+ ],
+ quality_filter: [
+ 'BluRay/UHD',
+ 'WEB/HD',
+ 'DVD/TV/SAT',
+ 'CAM/Screener',
+ 'Unknown',
+ ],
+ api_password: Env.MEDIAFUSION_API_PASSWORD,
+ mediaflow_config: null,
+ rpdb_config: null,
+ live_search_streams: options.liveSearchStreams || false,
+ contribution_streams: false,
+ mdblist_config: null,
+ },
+ false,
+ true
+ );
+
+ return encodedUserData;
+ }
+}
diff --git a/packages/core/src/presets/nuviostreams.ts b/packages/core/src/presets/nuviostreams.ts
new file mode 100644
index 00000000..04065241
--- /dev/null
+++ b/packages/core/src/presets/nuviostreams.ts
@@ -0,0 +1,215 @@
+import { Addon, Option, UserData, Resource, Stream } from '../db';
+import { Preset, baseOptions } from './preset';
+import { Env, SERVICE_DETAILS } from '../utils';
+import { constants, ServiceId } from '../utils';
+import { StreamParser } from '../parser';
+
+export class NuvioStreamsPreset extends Preset {
+ static override get METADATA() {
+ const supportedResources = [constants.STREAM_RESOURCE];
+ const regions = [
+ {
+ value: 'USA7',
+ label: 'USA East',
+ },
+ {
+ value: 'USA6',
+ label: 'USA West',
+ },
+ {
+ value: 'USA5',
+ label: 'USA Middle',
+ },
+ {
+ value: 'UK3',
+ label: 'United Kingdom',
+ },
+ {
+ value: 'CA1',
+ label: 'Canada',
+ },
+ {
+ value: 'FR1',
+ label: 'France',
+ },
+ {
+ value: 'DE2',
+ label: 'Germany',
+ },
+ {
+ value: 'HK1',
+ label: 'Hong Kong',
+ },
+ {
+ value: 'IN1',
+ label: 'India',
+ },
+ {
+ value: 'AU1',
+ label: 'Australia',
+ },
+ {
+ value: 'SZ',
+ label: 'China',
+ },
+ ];
+ const providers = [
+ {
+ value: 'showbox',
+ label: 'Showbox',
+ },
+ {
+ value: 'xprime',
+ label: 'XPrime',
+ },
+ {
+ value: 'hollymoviehd',
+ label: 'HollyMovieHD',
+ },
+ {
+ value: 'cuevana',
+ label: 'Cuevana',
+ },
+ {
+ value: 'soapertv',
+ label: 'Soapertv',
+ },
+ {
+ value: 'vidzee',
+ label: 'Vidzee',
+ },
+ {
+ value: 'hianime',
+ label: 'HiAnime',
+ },
+ {
+ value: 'vidsrc',
+ label: 'Vidsrc',
+ },
+ ];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'Nuvio Streams',
+ supportedResources,
+ Env.DEFAULT_NUVIOSTREAMS_TIMEOUT
+ ),
+ {
+ id: 'scraperApiKey',
+ name: 'Scraper API Key',
+ description:
+ 'Optionally provide a [ScraperAPI](https://www.scraperapi.com/) API Key from',
+ type: 'string',
+ required: false,
+ default: '',
+ },
+ {
+ id: 'showBoxCookie',
+ name: 'ShowBox Cookie',
+ description:
+ 'The cookie for the ShowBox provider. Highly recommended to get streams greater than 9GB. Log in at [Febbox](https://www.febbox.com/) > DevTools > Storage > Cookied > Copy the value of the `ui` cookie. ',
+ type: 'string',
+ required: false,
+ default: '',
+ },
+ {
+ id: 'showBoxRegion',
+ name: 'ShowBox Region',
+ description: 'The region to use for the ShowBox provider',
+ type: 'select',
+ required: false,
+ options: regions,
+ default: regions[0].value,
+ },
+ {
+ id: 'providers',
+ name: 'Providers',
+ description: 'The providers to use',
+ type: 'multi-select',
+ required: true,
+ options: providers,
+ default: providers.map((provider) => provider.value),
+ },
+ {
+ id: 'streamPassthrough',
+ name: 'Stream Passthrough',
+ description:
+ 'Whether to use the original stream name and description. Recommended to be left on in order to get all the information.',
+ type: 'boolean',
+ required: false,
+ default: true,
+ },
+ ];
+
+ return {
+ ID: 'nuvio-streams',
+ NAME: 'Nuvio Streams',
+ LOGO: 'https://raw.githubusercontent.com/tapframe/NuvioStreaming/main/assets/titlelogo.png',
+ URL: Env.NUVIOSTREAMS_URL,
+ TIMEOUT: Env.DEFAULT_NUVIOSTREAMS_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_NUVIOSTREAMS_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION: 'Free high quality streaming using multiple providers. ',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [constants.HTTP_STREAM_TYPE],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: this.generateManifestUrl(userData, options),
+ enabled: true,
+ streamPassthrough: options.streamPassthrough ?? true,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+
+ private static generateManifestUrl(
+ userData: UserData,
+ options: Record
+ ) {
+ const url = options.url || this.METADATA.URL;
+ if (url.endsWith('/manifest.json')) {
+ return url;
+ }
+
+ const cookie = options.showBoxCookie;
+ const providers = options.providers;
+ const scraperApiKey = options.scraperApiKey;
+ let config = [];
+ if (cookie) {
+ config.push(['cookie', cookie]);
+ }
+ if (options.showBoxRegion) {
+ config.push(['region', options.showBoxRegion]);
+ }
+ if (providers) {
+ config.push(['providers', providers.join(',')]);
+ }
+ if (scraperApiKey) {
+ config.push(['scraper_api_key', scraperApiKey]);
+ }
+
+ const configString = this.urlEncodeKeyValuePairs(config, '/', false);
+
+ return `${url}${configString ? '/' + configString : ''}/manifest.json`;
+ }
+}
diff --git a/packages/core/src/presets/opensubtitles.ts b/packages/core/src/presets/opensubtitles.ts
new file mode 100644
index 00000000..e32b9c58
--- /dev/null
+++ b/packages/core/src/presets/opensubtitles.ts
@@ -0,0 +1,57 @@
+import { Addon, Option, UserData } from '../db';
+import { Preset, baseOptions } from './preset';
+import { Env, RESOURCES, SUBTITLES_RESOURCE } from '../utils';
+
+export class OpenSubtitlesPreset extends Preset {
+ static override get METADATA() {
+ const supportedResources = [SUBTITLES_RESOURCE];
+ const options: Option[] = [
+ ...baseOptions(
+ 'OpenSubtitles',
+ supportedResources,
+ Env.DEFAULT_OPENSUBTITLES_TIMEOUT
+ ).filter((option) => option.id !== 'url'),
+ ];
+
+ return {
+ ID: 'opensubtitles',
+ NAME: 'OpenSubtitles v3',
+ LOGO: 'https://iwf1.com/scrapekod/icons/service.subtitles.opensubtitles_by_opensubtitles_dualsub.png',
+ URL: Env.OPENSUBTITLES_URL,
+ TIMEOUT: Env.DEFAULT_OPENSUBTITLES_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT:
+ Env.DEFAULT_OPENSUBTITLES_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION: 'OpenSubtitles addon',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: `${Env.OPENSUBTITLES_URL}/manifest.json`,
+ enabled: true,
+ library: false,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/orion.ts b/packages/core/src/presets/orion.ts
new file mode 100644
index 00000000..fda0fd23
--- /dev/null
+++ b/packages/core/src/presets/orion.ts
@@ -0,0 +1,177 @@
+import { Addon, Option, UserData, Resource, ParsedStream, Stream } from '../db';
+import { baseOptions, Preset } from './preset';
+import { Env } from '../utils';
+import { constants, ServiceId } from '../utils';
+import { StreamParser } from '../parser';
+
+class OrionStreamParser extends StreamParser {
+ protected override raiseErrorIfNecessary(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): void {
+ if (stream.title?.includes('ERROR')) {
+ throw new Error(stream.title);
+ }
+ }
+}
+
+export class OrionPreset extends Preset {
+ static override getParser(): typeof StreamParser {
+ return OrionStreamParser;
+ }
+
+ static override get METADATA() {
+ const supportedServices: ServiceId[] = [
+ constants.REALDEBRID_SERVICE,
+ constants.PREMIUMIZE_SERVICE,
+ constants.ALLEDEBRID_SERVICE,
+ // constants.TORBOX_SERVICE,
+ constants.DEBRIDLINK_SERVICE,
+ constants.OFFCLOUD_SERVICE,
+ ];
+
+ const supportedResources = [constants.STREAM_RESOURCE];
+
+ const options: Option[] = [
+ ...baseOptions('Orion', supportedResources, Env.DEFAULT_ORION_TIMEOUT),
+ {
+ id: 'orionApiKey',
+ name: 'Orion API Key',
+ description:
+ 'The API key for the Orion addon, obtain it from the [Orion Panel](https://panel.orionoid.com)',
+ type: 'password',
+ required: true,
+ },
+ {
+ id: 'showP2P',
+ name: 'Show P2P',
+ description: 'Show P2P results, even if a debrid service is enabled',
+ type: 'boolean',
+ default: false,
+ },
+ {
+ id: 'linkLimit',
+ name: 'Link Limit',
+ description: 'The maximum number of links to fetch from Orion.',
+ type: 'number',
+ default: 10,
+ constraints: {
+ max: 50,
+ min: 1,
+ },
+ },
+ {
+ id: 'services',
+ name: 'Services',
+ description:
+ 'Optionally override the services that are used. If not specified, then the services that are enabled and supported will be used.',
+ type: 'multi-select',
+ required: false,
+ options: supportedServices.map((service) => ({
+ value: service,
+ label: constants.SERVICE_DETAILS[service].name,
+ })),
+ default: undefined,
+ emptyIsUndefined: true,
+ },
+ ];
+
+ return {
+ ID: 'orion',
+ NAME: 'Orion',
+ LOGO: 'https://orionoid.com/web/images/logo/logo256.png',
+ URL: Env.ORION_STREMIO_ADDON_URL,
+ TIMEOUT: Env.DEFAULT_ORION_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_ORION_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: supportedServices,
+ DESCRIPTION: "Stremio's fastest Torrent/Debrid addon",
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [
+ constants.P2P_STREAM_TYPE,
+ constants.DEBRID_STREAM_TYPE,
+ ],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ // url can either be something like https://torrentio.com/ or it can be a custom manifest url.
+ // if it is a custom manifest url, return a single addon with the custom manifest url.
+ if (options?.url?.endsWith('/manifest.json')) {
+ return [this.generateAddon(userData, options, [])];
+ }
+
+ const usableServices = this.getUsableServices(userData, options.services);
+ // if no services are usable, use p2p
+ if (!usableServices || usableServices.length === 0) {
+ return [this.generateAddon(userData, options, [])];
+ }
+
+ const showP2P = options.showP2P ?? false;
+ const addonOptions = { ...options, showP2P: false };
+
+ let addons = usableServices.map((service) =>
+ this.generateAddon(userData, addonOptions, [service.id])
+ );
+
+ if (showP2P) {
+ // we only want to push a single p2p addon, rather than a p2p addon for each service.
+ addons.push(this.generateAddon(userData, addonOptions, []));
+ }
+
+ return addons;
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record,
+ serviceIds: ServiceId[]
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: `${options.name || this.METADATA.NAME} ${serviceIds.map((id) => constants.SERVICE_DETAILS[id].shortName).join(', ')}`,
+ manifestUrl: this.generateManifestUrl(userData, options, serviceIds),
+ enabled: true,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+
+ private static generateManifestUrl(
+ userData: UserData,
+ options: Record,
+ serviceIds: ServiceId[]
+ ) {
+ let url = options.url || this.METADATA.URL;
+ if (url.endsWith('/manifest.json')) {
+ return url;
+ }
+ url = url.replace(/\/$/, '');
+ const configString = this.base64EncodeJSON({
+ api: options.orionApiKey,
+ linkLimit: options.linkLimit.toString(),
+ sortValue: 'best',
+ audiochannels: '1,2,6,8',
+ videoquality:
+ 'hd8k,hd6k,hd4k,hd2k,hd1080,hd720,sd,scr1080,scr720,scr,cam1080,cam720,cam',
+ listOpt:
+ serviceIds.length > 0
+ ? options.showP2P
+ ? 'both'
+ : 'debrid'
+ : 'torrent',
+ debridservices: serviceIds,
+ audiolanguages: [],
+ additionalParameters: '',
+ });
+
+ return `${url}${configString ? '/' + configString : ''}/manifest.json`;
+ }
+}
diff --git a/packages/core/src/presets/peerflix.ts b/packages/core/src/presets/peerflix.ts
new file mode 100644
index 00000000..8bef8382
--- /dev/null
+++ b/packages/core/src/presets/peerflix.ts
@@ -0,0 +1,163 @@
+import { Addon, Option, UserData, Resource, Stream } from '../db';
+import { Preset, baseOptions } from './preset';
+import { Env, SERVICE_DETAILS } from '../utils';
+import { constants, ServiceId } from '../utils';
+import { StreamParser } from '../parser';
+
+export class PeerflixPreset extends Preset {
+ static override get METADATA() {
+ const supportedServices: ServiceId[] = [
+ constants.REALDEBRID_SERVICE,
+ constants.PREMIUMIZE_SERVICE,
+ constants.ALLEDEBRID_SERVICE,
+ constants.TORBOX_SERVICE,
+ constants.PUTIO_SERVICE,
+ constants.DEBRIDLINK_SERVICE,
+ constants.OFFCLOUD_SERVICE,
+ ];
+ const supportedResources = [
+ constants.STREAM_RESOURCE,
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ ];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'Peerflix',
+ supportedResources,
+ Env.DEFAULT_PEERFLIX_TIMEOUT
+ ),
+ {
+ id: 'services',
+ name: 'Services',
+ description:
+ 'Optionally override the services that are used. If not specified, then the services that are enabled and supported will be used.',
+ type: 'multi-select',
+ required: false,
+ options: supportedServices.map((service) => ({
+ value: service,
+ label: constants.SERVICE_DETAILS[service].name,
+ })),
+ default: undefined,
+ emptyIsUndefined: true,
+ },
+ {
+ id: 'useMultipleInstances',
+ name: 'Use Multiple Instances',
+ description:
+ 'When using multiple services, use a different Peerflix addon for each service, rather than using one instance for all services',
+ type: 'boolean',
+ default: false,
+ required: true,
+ },
+ {
+ id: 'showTorrentLinks',
+ name: 'Show P2P Streams for Uncached torrents',
+ description:
+ 'If enabled, the addon will show P2P streams for uncached torrents. This is useful for users who want to use the addon to stream torrents that are not cached by the debrid service.',
+ type: 'boolean',
+ default: false,
+ required: true,
+ },
+ ];
+
+ return {
+ ID: 'peerflix',
+ NAME: 'Peerflix',
+ LOGO: `https://config.peerflix.mov/static/media/logo.28f42024a3538640d047201d05416a09.svg`,
+ URL: Env.PEERFLIX_URL,
+ TIMEOUT: Env.DEFAULT_PEERFLIX_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_PEERFLIX_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: supportedServices,
+ REQUIRES_SERVICE: false,
+ DESCRIPTION:
+ 'Provides Spanish and English streams to Movies and TV Shows.',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [
+ constants.P2P_STREAM_TYPE,
+ constants.DEBRID_STREAM_TYPE,
+ ],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ if (options?.url?.endsWith('/manifest.json')) {
+ return [this.generateAddon(userData, options, [])];
+ }
+
+ const usableServices = this.getUsableServices(userData, options.services);
+
+ // if no services are usable, return a single addon with no services
+ if (!usableServices || usableServices.length === 0) {
+ return [this.generateAddon(userData, options, [])];
+ }
+
+ // if user has specified useMultipleInstances, return a single addon for each service
+ if (options?.useMultipleInstances) {
+ return usableServices.map((service) =>
+ this.generateAddon(userData, options, [service.id])
+ );
+ }
+
+ // return a single addon with all usable services
+ return [
+ this.generateAddon(
+ userData,
+ options,
+ usableServices.map((service) => service.id)
+ ),
+ ];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record,
+ services: ServiceId[]
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: `${options.name || this.METADATA.NAME} ${services.map((id) => constants.SERVICE_DETAILS[id].shortName).join(' | ')}`,
+ manifestUrl: this.generateManifestUrl(userData, services, options),
+ enabled: true,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+
+ private static generateManifestUrl(
+ userData: UserData,
+ services: ServiceId[],
+ options: Record
+ ) {
+ const url = options.url || this.METADATA.URL;
+ if (url.endsWith('/manifest.json')) {
+ return url;
+ }
+
+ let configOptions = services.map((service) => [
+ service,
+ this.getServiceCredential(service, userData, {
+ [constants.PUTIO_SERVICE]: (credentials: any) =>
+ `${credentials.clientId}@${credentials.token}`,
+ }),
+ ]);
+
+ if (options.showTorrentLinks) {
+ configOptions.push(['debridOptions', 'torrentlinks']);
+ }
+
+ const configString = configOptions.length
+ ? this.urlEncodeKeyValuePairs(configOptions)
+ : '';
+
+ return `${url}${configString ? '/' + configString : ''}/manifest.json`;
+ }
+}
diff --git a/packages/core/src/presets/preset.ts b/packages/core/src/presets/preset.ts
new file mode 100644
index 00000000..5e2512bb
--- /dev/null
+++ b/packages/core/src/presets/preset.ts
@@ -0,0 +1,229 @@
+import {
+ Option,
+ Resource,
+ Stream,
+ ParsedStream,
+ UserData,
+ PresetMetadata,
+ Addon,
+} from '../db';
+import { StreamParser } from '../parser';
+import { Env, ServiceId, constants } from '../utils';
+/**
+ *
+ * What modifications are needed for each preset:
+ *
+ * comet: apply FORCE_COMET_HOSTNAME, FORCE_COMET_PORT, FORCE_COMET_PROTOCOl to stream urls if they are defined
+ * dmm cast: need to split title by newline, replace trailing dashes, excluding lines with box emoji, and
+ * then joining the array back together.
+ * easynews,easynews+,easynews++: need to set type as usenet
+ * jackettio: apply FORCE_JACKETTIO_HOSTNAME, FORCE_JACKETTIO_PORT, FORCE_JACKETTIO_PROTOCOL to stream urls if they are defined
+ * mediafusion: need to add hint for folder name, 📁 emoji, and split on arrow, take last index.
+ * stremio-jacektt: need to inspect stream urls to extract service info.
+ * stremthruStore: need to mark each stream as 'inLibrary' and unset any parsed 'indexer'
+ * torbox: need to use different regex for probably everything.
+ * torrentio: extract folder name from first line
+ */
+
+// name: z.string().min(1),
+// enabled: z.boolean().optional(),
+// baseUrl: z.string().url().optional(),
+// timeout: z.number().min(1).optional(),
+// resources: ResourceList.optional(),
+
+export const baseOptions = (
+ name: string,
+ resources: Resource[],
+ timeout: number = Env.DEFAULT_TIMEOUT
+): Option[] => [
+ {
+ id: 'name',
+ name: 'Name',
+ description: 'What to call this addon',
+ type: 'string',
+ required: true,
+ default: name,
+ },
+ {
+ id: 'timeout',
+ name: 'Timeout',
+ description: 'The timeout for this addon',
+ type: 'number',
+ required: true,
+ default: timeout,
+ constraints: {
+ min: Env.MIN_TIMEOUT,
+ max: Env.MAX_TIMEOUT,
+ },
+ },
+ {
+ id: 'resources',
+ name: 'Resources',
+ description: 'Optionally override the resources to use ',
+ type: 'multi-select',
+ required: false,
+ default: resources,
+ options: resources.map((resource) => ({
+ label: resource,
+ value: resource,
+ })),
+ },
+ {
+ id: 'url',
+ name: 'URL',
+ description:
+ 'Optionally override either the manifest generated, or override the base url used when generating the manifests',
+ type: 'url',
+ required: false,
+ emptyIsUndefined: true,
+ default: undefined,
+ },
+];
+
+export abstract class Preset {
+ static get METADATA(): PresetMetadata {
+ throw new Error('METADATA must be implemented by derived classes');
+ }
+
+ static getParser(): typeof StreamParser {
+ return StreamParser;
+ }
+
+ /**
+ * Creates a preset from a preset id.
+ * @param presetId - The id of the preset to create.
+ * @returns The preset.
+ */
+
+ static generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ throw new Error('generateAddons must be implemented by derived classes');
+ }
+
+ // Utility functions for generating config strings
+ /**
+ * Encodes a JSON object into a base64 encoded string.
+ * @param json - The JSON object to encode.
+ * @returns The base64 encoded string.
+ */
+ protected static base64EncodeJSON(
+ json: any,
+ urlEncode: boolean = false, // url encode the string
+ makeUrlSafe: boolean = false // replace + with -, / with _ and = with nothing
+ ) {
+ let encoded = Buffer.from(JSON.stringify(json)).toString('base64');
+ if (makeUrlSafe) {
+ encoded = encoded
+ .replace(/\+/g, '-')
+ .replace(/\//g, '_')
+ .replace(/=+$/, '');
+ } else if (urlEncode) {
+ encoded = encodeURIComponent(encoded);
+ }
+ return encoded;
+ }
+
+ protected static urlEncodeJSON(json: any) {
+ return encodeURIComponent(JSON.stringify(json));
+ }
+
+ /**
+ * Transforms key-value pairs into a url encoded string
+ * @param options - The key-value pair object to encode.
+ * @returns The encoded string.
+ */
+ protected static urlEncodeKeyValuePairs(
+ options: Record | string[][],
+ separator: string = '|',
+ encode: boolean = true
+ ) {
+ const string = (Array.isArray(options) ? options : Object.entries(options))
+ .map(([key, value]) => `${key}=${value}`)
+ .join(separator);
+ return encode ? encodeURIComponent(string) : string;
+ }
+
+ protected static getUsableServices(
+ userData: UserData,
+ specifiedServices?: ServiceId[]
+ ) {
+ let usableServices = userData.services?.filter(
+ (service) =>
+ this.METADATA.SUPPORTED_SERVICES.includes(service.id) && service.enabled
+ );
+
+ if (specifiedServices) {
+ // Validate specified services exist and are enabled
+ for (const service of specifiedServices) {
+ const userService = userData.services?.find((s) => s.id === service);
+ const meta = Object.values(constants.SERVICE_DETAILS).find(
+ (s) => s.id === service
+ );
+ if (!userService || !userService.enabled || !userService.credentials) {
+ throw new Error(
+ `You have specified ${meta?.name || service} in your configuration, but it is not enabled or has missing credentials`
+ );
+ }
+ }
+ // Filter to only specified services
+ usableServices = usableServices?.filter((service) =>
+ specifiedServices.includes(service.id)
+ );
+ }
+
+ return usableServices;
+ }
+
+ protected static getServiceCredential(
+ serviceId: ServiceId,
+ userData: UserData,
+ specialCases?: Partial any>>
+ ) {
+ const service = constants.SERVICE_DETAILS[serviceId];
+ if (!service) {
+ throw new Error(`Service ${serviceId} not found`);
+ }
+
+ const serviceCredentials = userData.services?.find(
+ (service) => service.id === serviceId
+ )?.credentials;
+
+ if (!serviceCredentials) {
+ throw new Error(`No credentials found for service ${serviceId}`);
+ }
+
+ // Handle special cases if provided
+ if (specialCases?.[serviceId]) {
+ return specialCases[serviceId](serviceCredentials);
+ }
+
+ // handle seedr
+ if (serviceId === constants.SEEDR_SERVICE) {
+ if (serviceCredentials.encodedToken) {
+ return serviceCredentials.encodedToken;
+ }
+ throw new Error(
+ `Missing encoded token for ${serviceId}. Please add an encoded token using MediaFusion`
+ );
+ }
+ // handle easynews
+ if (serviceId === constants.EASYNEWS_SERVICE) {
+ if (!serviceCredentials.username || !serviceCredentials.password) {
+ throw new Error(
+ `Missing username or password for ${serviceId}. Please add a username and password.`
+ );
+ }
+ return `${serviceCredentials.username}:${serviceCredentials.password}`;
+ }
+ // Default case - API key
+ const { apiKey } = serviceCredentials;
+ if (!apiKey) {
+ throw new Error(
+ `Missing credentials for ${serviceId}. Please add an API key.`
+ );
+ }
+ return apiKey;
+ }
+}
diff --git a/packages/core/src/presets/presetManager.ts b/packages/core/src/presets/presetManager.ts
new file mode 100644
index 00000000..c2c36e42
--- /dev/null
+++ b/packages/core/src/presets/presetManager.ts
@@ -0,0 +1,137 @@
+import { PresetMetadata } from '../db';
+import { CometPreset } from './comet';
+import { CustomPreset } from './custom';
+import { MediaFusionPreset } from './mediafusion';
+import { StremthruStorePreset } from './stremthruStore';
+import { TorrentioPreset } from './torrentio';
+import { TorboxAddonPreset } from './torbox';
+import { EasynewsPreset } from './easynews';
+import { EasynewsPlusPreset } from './easynewsPlus';
+import { EasynewsPlusPlusPreset } from './easynewsPlusPlus';
+import { StremthruTorzPreset } from './stremthruTorz';
+import { DebridioPreset } from './debridio';
+import { AIOStreamsPreset } from './aiostreams';
+import { OpenSubtitlesPreset } from './opensubtitles';
+import { PeerflixPreset } from './peerflix';
+import { DMMCastPreset } from './dmmCast';
+import { MarvelPreset } from './marvel';
+import { JackettioPreset } from './jackettio';
+import { OrionPreset } from './orion';
+import { StreamFusionPreset } from './streamfusion';
+import { AnimeKitsuPreset } from './animeKitsu';
+import { NuvioStreamsPreset } from './nuviostreams';
+import { RpdbCatalogsPreset } from './rpdbCatalogs';
+import { TmdbCollectionsPreset } from './tmdbCollections';
+import { DebridioWatchtowerPreset } from './debridioWatchtower';
+import { DebridioTmdbPreset } from './debridioTmdb';
+import { StarWarsUniversePreset } from './starWarsUniverse';
+import { DebridioTvdbPreset } from './debridioTvdb';
+import { DcUniversePreset } from './dcUniverse';
+import { DebridioTvPreset } from './debridioTv';
+import { TorrentCatalogsPreset } from './torrentCatalogs';
+
+const PRESET_LIST: string[] = [
+ 'custom',
+ 'torrentio',
+ 'comet',
+ 'mediafusion',
+ 'stremthruTorz',
+ 'stremthruStore',
+ 'torbox',
+ 'jackettio',
+ 'peerflix',
+ 'easynews',
+ 'easynewsPlus',
+ 'easynewsPlusPlus',
+ 'nuvio-streams',
+ 'debridio',
+ 'debridio-tv',
+ 'debridio-watchtower',
+ 'streamfusion',
+ 'dmm-cast',
+ 'orion',
+ 'opensubtitles',
+ 'debridio-tmdb',
+ 'debridio-tvdb',
+ 'torrent-catalogs',
+ 'rpdb-catalogs',
+ 'tmdb-collections',
+ 'anime-kitsu',
+ 'marvel-universe',
+ 'star-wars-universe',
+ 'dc-universe',
+ 'aiostreams',
+];
+
+export class PresetManager {
+ static getPresetList(): PresetMetadata[] {
+ return PRESET_LIST.map((presetId) => this.fromId(presetId).METADATA);
+ }
+
+ static fromId(id: string) {
+ switch (id) {
+ case 'torrentio':
+ return TorrentioPreset;
+ case 'stremthruStore':
+ return StremthruStorePreset;
+ case 'stremthruTorz':
+ return StremthruTorzPreset;
+ case 'comet':
+ return CometPreset;
+ case 'mediafusion':
+ return MediaFusionPreset;
+ case 'custom':
+ return CustomPreset;
+ case 'torbox':
+ return TorboxAddonPreset;
+ case 'jackettio':
+ return JackettioPreset;
+ case 'easynews':
+ return EasynewsPreset;
+ case 'easynewsPlus':
+ return EasynewsPlusPreset;
+ case 'easynewsPlusPlus':
+ return EasynewsPlusPlusPreset;
+ case 'debridio':
+ return DebridioPreset;
+ case 'debridio-watchtower':
+ return DebridioWatchtowerPreset;
+ case 'debridio-tv':
+ return DebridioTvPreset;
+ case 'debridio-tmdb':
+ return DebridioTmdbPreset;
+ case 'debridio-tvdb':
+ return DebridioTvdbPreset;
+ case 'aiostreams':
+ return AIOStreamsPreset;
+ case 'opensubtitles':
+ return OpenSubtitlesPreset;
+ case 'peerflix':
+ return PeerflixPreset;
+ case 'dmm-cast':
+ return DMMCastPreset;
+ case 'marvel-universe':
+ return MarvelPreset;
+ case 'orion':
+ return OrionPreset;
+ case 'streamfusion':
+ return StreamFusionPreset;
+ case 'anime-kitsu':
+ return AnimeKitsuPreset;
+ case 'nuvio-streams':
+ return NuvioStreamsPreset;
+ case 'torrent-catalogs':
+ return TorrentCatalogsPreset;
+ case 'rpdb-catalogs':
+ return RpdbCatalogsPreset;
+ case 'tmdb-collections':
+ return TmdbCollectionsPreset;
+ case 'star-wars-universe':
+ return StarWarsUniversePreset;
+ case 'dc-universe':
+ return DcUniversePreset;
+ default:
+ throw new Error(`Preset ${id} not found`);
+ }
+ }
+}
diff --git a/packages/core/src/presets/rpdbCatalogs.ts b/packages/core/src/presets/rpdbCatalogs.ts
new file mode 100644
index 00000000..f0fe6ebd
--- /dev/null
+++ b/packages/core/src/presets/rpdbCatalogs.ts
@@ -0,0 +1,87 @@
+import { Addon, Option, UserData } from '../db';
+import { Preset, baseOptions } from './preset';
+import { constants, Env } from '../utils';
+
+export class RpdbCatalogsPreset extends Preset {
+ private static catalogs = [
+ {
+ label: 'Movies',
+ value: 'movies',
+ },
+ {
+ label: 'Series',
+ value: 'series',
+ },
+ {
+ label: 'Other (News / Talk-Shows / Reality TV etc.)',
+ value: 'other',
+ },
+ ];
+ static override get METADATA() {
+ const supportedResources = [constants.CATALOG_RESOURCE];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'RPDB Catalogs',
+ supportedResources,
+ Env.DEFAULT_RPDB_CATALOGS_TIMEOUT
+ ).filter((option) => option.id !== 'url'),
+ // series movies animations xmen release-order marvel-mcu
+ {
+ id: 'catalogs',
+ name: 'Catalogs',
+ description: 'The catalogs to display',
+ type: 'multi-select',
+ required: true,
+ options: this.catalogs,
+ default: this.catalogs.map((catalog) => catalog.value),
+ },
+ ];
+
+ return {
+ ID: 'rpdb-catalogs',
+ NAME: 'RPDB Catalogs',
+ LOGO: `${Env.RPDB_CATALOGS_URL}/addon-logo.png`,
+ URL: Env.RPDB_CATALOGS_URL,
+ TIMEOUT: Env.DEFAULT_RPDB_CATALOGS_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT:
+ Env.DEFAULT_RPDB_CATALOGS_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION: 'Catalogs to accurately track new / popular / best release!',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ if (!userData.rpdbApiKey) {
+ throw new Error(
+ `${this.METADATA.NAME} requires an RPDB API Key. Please provide one in the services section`
+ );
+ }
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: `${Env.RPDB_CATALOGS_URL}/${userData.rpdbApiKey}/poster-default/${options.catalogs.join('_')}/manifest.json`,
+ enabled: true,
+ library: false,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/starWarsUniverse.ts b/packages/core/src/presets/starWarsUniverse.ts
new file mode 100644
index 00000000..8d12d2d5
--- /dev/null
+++ b/packages/core/src/presets/starWarsUniverse.ts
@@ -0,0 +1,129 @@
+import { Addon, Option, UserData } from '../db';
+import { Preset, baseOptions } from './preset';
+import { constants, Env } from '../utils';
+
+export class StarWarsUniversePreset extends Preset {
+ private static catalogs = [
+ {
+ label: 'Movies & Series Chronological',
+ value: 'sw-movies-series-chronological',
+ },
+ {
+ label: 'Movies & Series Release',
+ value: 'sw-movies-series-release',
+ },
+ {
+ label: 'Skywalker Saga',
+ value: 'sw-skywalker-saga',
+ },
+ {
+ label: 'Anthology Films',
+ value: 'sw-anthology-films',
+ },
+ {
+ label: 'Live-Action Series',
+ value: 'sw-live-action-series',
+ },
+ {
+ label: 'Animated Series',
+ value: 'sw-animated-series',
+ },
+ {
+ label: 'Micro-Series & Shorts',
+ value: 'sw-micro-series-shorts',
+ },
+ {
+ label: 'High Republic Era',
+ value: 'sw-high-republic-era',
+ },
+ {
+ label: 'Empire Era',
+ value: 'sw-empire-era',
+ },
+ {
+ label: 'New Republic Era',
+ value: 'sw-new-republic-era',
+ },
+ {
+ label: 'Bounty Hunters & Underworld',
+ value: 'sw-bounty-hunters-underworld',
+ },
+ {
+ label: 'Jedi & Sith Lore',
+ value: 'sw-jedi-sith-lore',
+ },
+ {
+ label: 'Droids & Creatures',
+ value: 'sw-droids-creatures',
+ },
+ ];
+ static override get METADATA() {
+ const supportedResources = [
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ ];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'Star Wars Universe',
+ supportedResources,
+ Env.DEFAULT_STAR_WARS_UNIVERSE_TIMEOUT
+ ).filter((option) => option.id !== 'url'),
+ {
+ id: 'catalogs',
+ name: 'Catalogs',
+ description: 'The catalogs to display',
+ type: 'multi-select',
+ required: true,
+ options: this.catalogs,
+ default: this.catalogs.map((catalog) => catalog.value),
+ },
+ ];
+
+ return {
+ ID: 'star-wars-universe',
+ NAME: 'Star Wars Universe',
+ LOGO: 'https://www.freeiconspng.com/uploads/logo-star-wars-png-4.png',
+ URL: Env.DEFAULT_STAR_WARS_UNIVERSE_URL,
+ TIMEOUT: Env.DEFAULT_STAR_WARS_UNIVERSE_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT:
+ Env.DEFAULT_STAR_WARS_UNIVERSE_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION:
+ 'Explore the Star Wars Universe by sagas, series, eras, and more!',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ const config =
+ options.catalogs.length !== this.catalogs.length
+ ? options.catalogs.join('%2C')
+ : '';
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: `${Env.DEFAULT_STAR_WARS_UNIVERSE_URL}/${config ? 'catalog/' + config + '/' : ''}manifest.json`,
+ enabled: true,
+ library: false,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/streamfusion.ts b/packages/core/src/presets/streamfusion.ts
new file mode 100644
index 00000000..8d88c48f
--- /dev/null
+++ b/packages/core/src/presets/streamfusion.ts
@@ -0,0 +1,251 @@
+import { Addon, Option, UserData, Resource } from '../db';
+import { baseOptions, Preset } from './preset';
+import { Env } from '../utils';
+import { constants, ServiceId } from '../utils';
+
+export class StreamFusionPreset extends Preset {
+ static override get METADATA() {
+ const supportedServices: ServiceId[] = [
+ constants.REALDEBRID_SERVICE,
+ constants.PREMIUMIZE_SERVICE,
+ constants.ALLEDEBRID_SERVICE,
+ constants.TORBOX_SERVICE,
+ constants.EASYDEBRID_SERVICE,
+ constants.DEBRIDLINK_SERVICE,
+ constants.OFFCLOUD_SERVICE,
+ constants.PIKPAK_SERVICE,
+ ];
+
+ const supportedResources = [
+ constants.STREAM_RESOURCE,
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ ];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'StreamFusion',
+ supportedResources,
+ Env.DEFAULT_STREAMFUSION_TIMEOUT
+ ),
+ {
+ id: 'streamFusionApiKey',
+ name: 'StreamFusion API Key',
+ description:
+ 'The API key for the StreamFusion service. You can get it by sending the `/generate` command to the [StremioFR Telegram bot](https://t.me/Stremiofr_bot)',
+ type: 'password',
+ required: true,
+ },
+ {
+ id: 'torboxSearch',
+ name: 'Torbox Search',
+ description:
+ "Enable or disable the use of Torbox's Public Torrent Search Engine",
+ type: 'boolean',
+ required: false,
+ default: false,
+ },
+ {
+ id: 'torboxUsenet',
+ name: 'Torbox Usenet',
+ description:
+ "Enable or disable the use of Torbox's Usenet search and download functionality.",
+ type: 'boolean',
+ required: false,
+ default: false,
+ },
+ {
+ id: 'catalogs',
+ name: 'Catalogs',
+ description: 'What catalogs should be displayed',
+ type: 'multi-select',
+ required: false,
+ options: [
+ {
+ value: 'yggtorrent',
+ label: 'YggTorrent',
+ },
+ {
+ value: 'yggflix',
+ label: 'YggFlix',
+ },
+ ],
+ default: ['yggtorrent', 'yggflix'],
+ },
+ {
+ id: 'torrenting',
+ name: 'Torrenting',
+ description:
+ "Use direct torrent streaming instead of debrid. If you haven't provided any debrid SERVICES, torrenting is automatically used and this option does not apply to you.",
+ type: 'boolean',
+ required: false,
+ default: false,
+ },
+ {
+ id: 'services',
+ name: 'Services',
+ description:
+ 'Optionally override the services that are used. If not specified, then the services that are enabled and supported will be used.',
+ type: 'multi-select',
+ required: false,
+ options: supportedServices.map((service) => ({
+ value: service,
+ label: constants.SERVICE_DETAILS[service].name,
+ })),
+ default: undefined,
+ emptyIsUndefined: true,
+ },
+ ];
+
+ return {
+ ID: 'streamfusion',
+ NAME: 'StreamFusion',
+ LOGO: 'https://stream-fusion.stremiofr.com/static/logo-stream-fusion.png',
+ URL: Env.DEFAULT_STREAMFUSION_URL,
+ TIMEOUT: Env.DEFAULT_STREAMFUSION_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_STREAMFUSION_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: supportedServices,
+ DESCRIPTION: 'Stremio addon focusing on french content',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [
+ constants.DEBRID_STREAM_TYPE,
+ constants.P2P_STREAM_TYPE,
+ ],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ if (options?.url?.endsWith('/manifest.json')) {
+ return [this.generateAddon(userData, options, [])];
+ }
+
+ const usableServices = this.getUsableServices(userData, options.services);
+ if (!usableServices || usableServices.length === 0) {
+ throw new Error(
+ `${this.METADATA.NAME} requires at least one usable service from the list of supported services: ${this.METADATA.SUPPORTED_SERVICES.map((service) => constants.SERVICE_DETAILS[service].name).join(', ')}`
+ );
+ }
+
+ return [
+ this.generateAddon(
+ userData,
+ options,
+ usableServices.map((service) => service.id)
+ ),
+ ];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record,
+ serviceIds: ServiceId[]
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: `${options.name || this.METADATA.NAME} ${serviceIds
+ .map((serviceId) => constants.SERVICE_DETAILS[serviceId].shortName)
+ .join(' | ')}`,
+ manifestUrl: this.generateManifestUrl(userData, options, serviceIds),
+ enabled: true,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+
+ private static generateManifestUrl(
+ userData: UserData,
+ options: Record,
+ serviceIds: ServiceId[]
+ ) {
+ let url = options.url || this.METADATA.URL;
+ if (url.endsWith('/manifest.json')) {
+ return url;
+ }
+
+ const specialCases = {
+ [constants.OFFCLOUD_SERVICE]: (credentials: any) =>
+ `${credentials.email}:${credentials.password}`,
+ [constants.PIKPAK_SERVICE]: (credentials: any) =>
+ `${credentials.email}:${credentials.password}`,
+ };
+
+ url = url.replace(/\/$/, '');
+ const configString = this.base64EncodeJSON({
+ addonHost: options.url ? new URL(options.url).origin : this.METADATA.URL,
+ apiKey: options.streamFusionApiKey,
+ service: serviceIds.map(
+ (serviceId) => constants.SERVICE_DETAILS[serviceId].name
+ ),
+ // this probably doesnt work for RD and AD as configuration page uses oauth flow and puts json response from RD/AD as values.
+ RDToken: serviceIds.includes(constants.REALDEBRID_SERVICE)
+ ? this.getServiceCredential(constants.REALDEBRID_SERVICE, userData)
+ : '',
+ ADToken: serviceIds.includes(constants.ALLEDEBRID_SERVICE)
+ ? this.getServiceCredential(constants.ALLEDEBRID_SERVICE, userData)
+ : '',
+ TBToken: serviceIds.includes(constants.TORBOX_SERVICE)
+ ? this.getServiceCredential(constants.TORBOX_SERVICE, userData)
+ : '',
+ PMToken: serviceIds.includes(constants.PREMIUMIZE_SERVICE)
+ ? this.getServiceCredential(constants.PREMIUMIZE_SERVICE, userData)
+ : '',
+ debridlinkApiKey: serviceIds.includes(constants.DEBRIDLINK_SERVICE)
+ ? this.getServiceCredential(constants.DEBRIDLINK_SERVICE, userData)
+ : '',
+ easydebridApiKey: serviceIds.includes(constants.EASYDEBRID_SERVICE)
+ ? this.getServiceCredential(constants.EASYDEBRID_SERVICE, userData)
+ : '',
+ offcloudCredentials: serviceIds.includes(constants.OFFCLOUD_SERVICE)
+ ? this.getServiceCredential(
+ constants.OFFCLOUD_SERVICE,
+ userData,
+ specialCases
+ )
+ : '',
+ pikpakCredentials: serviceIds.includes(constants.PIKPAK_SERVICE)
+ ? this.getServiceCredential(
+ constants.PIKPAK_SERVICE,
+ userData,
+ specialCases
+ )
+ : '',
+ TBUsenet: options.torboxUsenet,
+ TBSearch: options.torboxSearch,
+ maxSize: 18,
+ exclusionKeywords: [],
+ languages: ['en', 'fr', 'multi'],
+ sort: 'quality',
+ resultsPerQuality: 10,
+ maxResults: 30,
+ minCachedResults: 10,
+ exclusion: [],
+ cacheUrl: 'https://stremio-jackett-cacher.elfhosted.com/',
+ cache: true,
+ zilean: false, //true,
+ yggflix: false, //true,
+ sharewood: false, //true,
+ yggtorrentCtg: options.catalogs?.includes('yggtorrent') ?? false,
+ yggflixCtg: options.catalogs?.includes('yggflix') ?? false,
+ torrenting:
+ serviceIds.length === 0 ? true : (options.torrenting ?? false),
+ debrid: serviceIds.length > 0,
+ metadataProvider: 'tmdb',
+ debridDownloader:
+ serviceIds.length > 0
+ ? constants.SERVICE_DETAILS[serviceIds[0]].name
+ : '',
+ stremthru: true,
+ stremthruUrl: Env.DEFAULT_STREAMFUSION_STREMTHRU_URL,
+ });
+
+ return `${url}${configString ? '/' + configString : ''}/manifest.json`;
+ }
+}
diff --git a/packages/core/src/presets/stremthruStore.ts b/packages/core/src/presets/stremthruStore.ts
new file mode 100644
index 00000000..40acd586
--- /dev/null
+++ b/packages/core/src/presets/stremthruStore.ts
@@ -0,0 +1,149 @@
+import { Addon, Option, UserData, Resource, Stream } from '../db';
+import { baseOptions, Preset } from './preset';
+import { Env } from '../utils';
+import { constants, ServiceId } from '../utils';
+import { StreamParser } from '../parser';
+
+export class StremthruStorePreset extends Preset {
+ static override get METADATA() {
+ const supportedServices: ServiceId[] = [
+ constants.REALDEBRID_SERVICE,
+ constants.PREMIUMIZE_SERVICE,
+ constants.ALLEDEBRID_SERVICE,
+ constants.TORBOX_SERVICE,
+ constants.EASYDEBRID_SERVICE,
+ constants.DEBRIDLINK_SERVICE,
+ constants.OFFCLOUD_SERVICE,
+ constants.PIKPAK_SERVICE,
+ ];
+
+ const supportedResources = [
+ constants.STREAM_RESOURCE,
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ ];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'StremThru Store',
+ supportedResources,
+ Env.DEFAULT_STREMTHRU_STORE_TIMEOUT
+ ),
+ {
+ id: 'services',
+ name: 'Services',
+ description:
+ 'Optionally override the services that are used. If not specified, then the services that are enabled and supported will be used.',
+ type: 'multi-select',
+ required: false,
+ options: supportedServices.map((service) => ({
+ value: service,
+ label: constants.SERVICE_DETAILS[service].name,
+ })),
+ default: undefined,
+ emptyIsUndefined: true,
+ },
+ {
+ id: 'webDl',
+ name: 'Web DL',
+ description: 'Enable web DL',
+ type: 'boolean',
+ },
+ ];
+
+ return {
+ ID: 'stremthruStore',
+ NAME: 'StremThru Store',
+ LOGO: 'https://emojiapi.dev/api/v1/sparkles/256.png',
+ URL: Env.STREMTHRU_STORE_URL,
+ TIMEOUT: Env.DEFAULT_STREMTHRU_STORE_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT:
+ Env.DEFAULT_STREMTHRU_STORE_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: supportedServices,
+ DESCRIPTION: 'Access your debrid library through catalogs and streams.',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [constants.DEBRID_STREAM_TYPE],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ // url can either be something like https://torrentio.com/ or it can be a custom manifest url.
+ // if it is a custom manifest url, return a single addon with the custom manifest url.
+ if (options?.url?.endsWith('/manifest.json')) {
+ return [this.generateAddon(userData, options, undefined)];
+ }
+
+ const usableServices = this.getUsableServices(userData, options.services);
+ // if no services are usable, throw an error
+ if (!usableServices || usableServices.length === 0) {
+ throw new Error(
+ `${this.METADATA.NAME} requires at least one usable service, but none were found. Please enable at least one of the following services: ${this.METADATA.SUPPORTED_SERVICES.join(
+ ', '
+ )}`
+ );
+ }
+
+ return usableServices.map((service) =>
+ this.generateAddon(userData, options, service.id)
+ );
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record,
+ serviceId?: ServiceId
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: serviceId
+ ? `${options.name || this.METADATA.NAME} ${constants.SERVICE_DETAILS[serviceId].shortName}`
+ : options.name || this.METADATA.NAME,
+ manifestUrl: this.generateManifestUrl(userData, options, serviceId),
+ enabled: true,
+ library: true,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+
+ private static generateManifestUrl(
+ userData: UserData,
+ options: Record,
+ serviceId: ServiceId | undefined
+ ) {
+ let url = options.url || this.METADATA.URL;
+ if (url.endsWith('/manifest.json')) {
+ return url;
+ }
+ url = url.replace(/\/$/, '');
+ if (!serviceId) {
+ throw new Error(
+ `${this.METADATA.NAME} requires at least one service, but none were found. Please enable at least one of the following services: ${this.METADATA.SUPPORTED_SERVICES.join(
+ ', '
+ )}`
+ );
+ }
+ const configString = this.base64EncodeJSON({
+ store_name: serviceId,
+ store_token: this.getServiceCredential(serviceId, userData, {
+ [constants.OFFCLOUD_SERVICE]: (credentials: any) =>
+ `${credentials.email}:${credentials.password}`,
+ [constants.PIKPAK_SERVICE]: (credentials: any) =>
+ `${credentials.email}:${credentials.password}`,
+ }),
+ hide_catalog: false,
+ hide_stream: false,
+ web_dl: options.webDl ?? false,
+ });
+
+ return `${url}${configString ? '/' + configString : ''}/manifest.json`;
+ }
+}
diff --git a/packages/core/src/presets/stremthruTorz.ts b/packages/core/src/presets/stremthruTorz.ts
new file mode 100644
index 00000000..a7828105
--- /dev/null
+++ b/packages/core/src/presets/stremthruTorz.ts
@@ -0,0 +1,171 @@
+import { Addon, Option, UserData, Resource, ParsedStream, Stream } from '../db';
+import { baseOptions, Preset } from './preset';
+import { Env } from '../utils';
+import { constants, ServiceId } from '../utils';
+import { StreamParser } from '../parser';
+
+class StremthruTorzStreamParser extends StreamParser {
+ // ensure release groups aren't misidentified as indexers
+ protected override getIndexer(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ return undefined;
+ }
+}
+
+export class StremthruTorzPreset extends Preset {
+ static override getParser(): typeof StreamParser {
+ return StremthruTorzStreamParser;
+ }
+
+ static override get METADATA() {
+ const supportedServices: ServiceId[] = [
+ constants.REALDEBRID_SERVICE,
+ constants.PREMIUMIZE_SERVICE,
+ constants.ALLEDEBRID_SERVICE,
+ constants.TORBOX_SERVICE,
+ constants.EASYDEBRID_SERVICE,
+ constants.DEBRIDLINK_SERVICE,
+ constants.OFFCLOUD_SERVICE,
+ constants.PIKPAK_SERVICE,
+ ];
+
+ const supportedResources = [constants.STREAM_RESOURCE];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'StremThru Torz',
+ supportedResources,
+ Env.DEFAULT_STREMTHRU_STORE_TIMEOUT
+ ),
+ {
+ id: 'services',
+ name: 'Services',
+ description:
+ 'Optionally override the services that are used. If not specified, then the services that are enabled and supported will be used.',
+ type: 'multi-select',
+ required: false,
+ options: supportedServices.map((service) => ({
+ value: service,
+ label: constants.SERVICE_DETAILS[service].name,
+ })),
+ default: undefined,
+ emptyIsUndefined: true,
+ },
+ {
+ id: 'useMultipleInstances',
+ name: 'Use Multiple Instances',
+ description:
+ 'StremThru Torz supports multiple services in one instance of the addon - which is used by default. If this is enabled, then the addon will be created for each service.',
+ type: 'boolean',
+ default: false,
+ },
+ ];
+
+ return {
+ ID: 'stremthruTorz',
+ NAME: 'StremThru Torz',
+ LOGO: 'https://emojiapi.dev/api/v1/sparkles/256.png',
+ URL: Env.STREMTHRU_TORZ_URL,
+ TIMEOUT: Env.DEFAULT_STREMTHRU_TORZ_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT:
+ Env.DEFAULT_STREMTHRU_TORZ_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: supportedServices,
+ DESCRIPTION:
+ 'Access a crowdsourced torrent library supplemented by DMM hashlists',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [constants.DEBRID_STREAM_TYPE],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ // url can either be something like https://torrentio.com/ or it can be a custom manifest url.
+ // if it is a custom manifest url, return a single addon with the custom manifest url.
+ if (options?.url?.endsWith('/manifest.json')) {
+ return [this.generateAddon(userData, options, [])];
+ }
+
+ const usableServices = this.getUsableServices(userData, options.services);
+ // if no services are usable, throw an error
+ if (!usableServices || usableServices.length === 0) {
+ throw new Error(
+ `${this.METADATA.NAME} requires at least one usable service, but none were found. Please enable at least one of the following services: ${this.METADATA.SUPPORTED_SERVICES.join(
+ ', '
+ )}`
+ );
+ }
+
+ if (options.useMultipleInstances) {
+ return usableServices.map((service) =>
+ this.generateAddon(userData, options, [service.id])
+ );
+ }
+
+ return [
+ this.generateAddon(
+ userData,
+ options,
+ usableServices.map((s) => s.id)
+ ),
+ ];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record,
+ serviceIds: ServiceId[]
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: `${options.name || this.METADATA.NAME} ${serviceIds.map((id) => constants.SERVICE_DETAILS[id].shortName).join(' | ')}`,
+ manifestUrl: this.generateManifestUrl(userData, options, serviceIds),
+ enabled: true,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+
+ private static generateManifestUrl(
+ userData: UserData,
+ options: Record,
+ serviceIds: ServiceId[]
+ ) {
+ let url = options.url || this.METADATA.URL;
+ if (url.endsWith('/manifest.json')) {
+ return url;
+ }
+ url = url.replace(/\/$/, '');
+ if (!serviceIds || serviceIds.length === 0) {
+ throw new Error(
+ `${this.METADATA.NAME} requires at least one service, but none were found. Please enable at least one of the following services: ${this.METADATA.SUPPORTED_SERVICES.join(
+ ', '
+ )}`
+ );
+ }
+ const configString = this.base64EncodeJSON({
+ stores: serviceIds.map((serviceId) => ({
+ c:
+ serviceId === constants.PIKPAK_SERVICE
+ ? 'pp'
+ : constants.SERVICE_DETAILS[serviceId].shortName.toLowerCase(),
+ t: this.getServiceCredential(serviceId, userData, {
+ [constants.OFFCLOUD_SERVICE]: (credentials: any) =>
+ `${credentials.email}:${credentials.password}`,
+ [constants.PIKPAK_SERVICE]: (credentials: any) =>
+ `${credentials.email}:${credentials.password}`,
+ }),
+ })),
+ });
+
+ return `${url}${configString ? '/' + configString : ''}/manifest.json`;
+ }
+}
diff --git a/packages/core/src/presets/tmdbCollections.ts b/packages/core/src/presets/tmdbCollections.ts
new file mode 100644
index 00000000..6b2df3c2
--- /dev/null
+++ b/packages/core/src/presets/tmdbCollections.ts
@@ -0,0 +1,104 @@
+import { Addon, Option, UserData } from '../db';
+import { Preset, baseOptions } from './preset';
+import { constants, Env, FULL_LANGUAGE_MAPPING } from '../utils';
+
+export class TmdbCollectionsPreset extends Preset {
+ static override get METADATA() {
+ const supportedResources = [
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ ];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'TMDB Collections',
+ supportedResources,
+ Env.DEFAULT_TMDB_COLLECTIONS_TIMEOUT
+ ),
+ {
+ id: 'enableAdultContent',
+ name: 'Enable Adult Content',
+ description: 'Enable adult content in the catalogs',
+ type: 'boolean',
+ default: false,
+ required: false,
+ },
+ {
+ id: 'enableSearch',
+ name: 'Enable Search',
+ description: 'Enable search in the catalogs',
+ type: 'boolean',
+ default: true,
+ required: false,
+ },
+ {
+ id: 'language',
+ name: 'Language',
+ description: 'The language of the catalogs',
+ type: 'select',
+ default: 'en',
+ options: FULL_LANGUAGE_MAPPING.sort((a, b) =>
+ a.english_name.localeCompare(b.english_name)
+ )
+ .filter(
+ (language, index, self) =>
+ index ===
+ self.findIndex((l) => l.iso_639_1 === language.iso_639_1)
+ )
+ .map((language) => ({
+ label: language.english_name.split('(')[0].trim(),
+ value: `${language.iso_639_1}`,
+ })),
+ required: false,
+ },
+ ];
+
+ return {
+ ID: 'tmdb-collections',
+ NAME: 'TMDB Collections',
+ LOGO: 'https://raw.githubusercontent.com/youchi1/tmdb-collections/main/Images/logo.png',
+ URL: Env.TMDB_COLLECTIONS_URL,
+ TIMEOUT: Env.DEFAULT_TMDB_COLLECTIONS_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT:
+ Env.DEFAULT_TMDB_COLLECTIONS_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION: 'Catalogs for the TMDB Collections',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ const config = this.urlEncodeJSON({
+ enableAdultContent: options.enableAdultContent ?? false,
+ enableSearch: options.enableSearch ?? true,
+ language: options.language,
+ catalogList: ['popular', 'topRated', 'newReleases'],
+ discoverOnly: { popular: false, topRated: false, newReleases: false },
+ });
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: `${this.METADATA.URL}/${config}/manifest.json`,
+ enabled: true,
+ library: false,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/torbox.ts b/packages/core/src/presets/torbox.ts
new file mode 100644
index 00000000..57ddeb98
--- /dev/null
+++ b/packages/core/src/presets/torbox.ts
@@ -0,0 +1,159 @@
+import { Addon, Option, UserData, Resource, ParsedStream } from '../db';
+import { baseOptions, Preset } from './preset';
+import { Env } from '../utils';
+import { constants, ServiceId } from '../utils';
+import { StreamParser } from '../parser';
+import { Stream } from '../db';
+
+class TorboxStreamParser extends StreamParser {
+ override getSeeders(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): number | undefined {
+ return (stream as any).seeders && (stream as any).seeders >= 0
+ ? (stream as any).seeders
+ : undefined;
+ }
+ override get ageRegex() {
+ return /\|\sAge:\s([0-9]+[dmyh])/i;
+ }
+ override get indexerRegex() {
+ return /Source:\s*([^\n]+)/;
+ }
+ override getInfoHash(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ return (stream as any).hash;
+ }
+ override getInLibrary(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): boolean {
+ return (stream as any).is_your_media || stream.name?.includes('Your Media');
+ }
+ protected override getService(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): ParsedStream['service'] | undefined {
+ return {
+ id: constants.TORBOX_SERVICE,
+ cached: (stream as any).is_cached ?? true,
+ };
+ }
+
+ protected override getMessage(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string | undefined {
+ if (stream.description?.includes('Click play to start')) {
+ currentParsedStream.filename = undefined;
+ return 'Click play to start streaming your media';
+ }
+ return undefined;
+ }
+
+ protected override getStreamType(
+ stream: Stream,
+ service: ParsedStream['service'],
+ currentParsedStream: ParsedStream
+ ): ParsedStream['type'] {
+ if ((stream as any).type === 'usenet') {
+ return constants.USENET_STREAM_TYPE;
+ }
+ const type = stream.description?.match(/Type:\s*([^\n\s]+)/)?.[1];
+ if (type) {
+ if (type.includes('Torrent')) {
+ return constants.DEBRID_STREAM_TYPE;
+ } else if (type.includes('Usenet')) {
+ return constants.USENET_STREAM_TYPE;
+ }
+ }
+ return super.getStreamType(stream, service, currentParsedStream);
+ }
+}
+
+export class TorboxAddonPreset extends Preset {
+ static override getParser(): typeof StreamParser {
+ return TorboxStreamParser;
+ }
+
+ static override get METADATA() {
+ const supportedServices: ServiceId[] = [constants.TORBOX_SERVICE];
+
+ const supportedResources = [
+ constants.STREAM_RESOURCE,
+ constants.META_RESOURCE,
+ constants.CATALOG_RESOURCE,
+ ];
+
+ const options: Option[] = [
+ ...baseOptions('TorBox', supportedResources, Env.DEFAULT_TORBOX_TIMEOUT),
+ ];
+
+ return {
+ ID: 'torbox',
+ NAME: 'TorBox',
+ LOGO: 'https://torbox.app/android-chrome-512x512.png',
+ URL: Env.TORBOX_STREMIO_URL,
+ TIMEOUT: Env.DEFAULT_TORBOX_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_TORBOX_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: supportedServices,
+ DESCRIPTION:
+ 'Provides torrent and usenet streams for users of TorBox.app',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [
+ constants.DEBRID_STREAM_TYPE,
+ constants.USENET_STREAM_TYPE,
+ ],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: this.generateManifestUrl(userData, options),
+ enabled: true,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+
+ private static generateManifestUrl(
+ userData: UserData,
+ options: Record
+ ) {
+ let url = options.url || this.METADATA.URL;
+ if (url.endsWith('/manifest.json')) {
+ return url;
+ }
+ url = url.replace(/\/$/, '');
+ const torboxApiKey = this.getServiceCredential(
+ constants.TORBOX_SERVICE,
+ userData
+ );
+ if (!torboxApiKey) {
+ throw new Error(
+ `${this.METADATA.NAME} requires the Torbox service to be enabled.`
+ );
+ }
+
+ return `${url}/${torboxApiKey}/manifest.json`;
+ }
+}
diff --git a/packages/core/src/presets/torrentCatalogs.ts b/packages/core/src/presets/torrentCatalogs.ts
new file mode 100644
index 00000000..a0e90f35
--- /dev/null
+++ b/packages/core/src/presets/torrentCatalogs.ts
@@ -0,0 +1,59 @@
+import { Addon, Option, UserData } from '../db';
+import { Preset, baseOptions } from './preset';
+import { constants, Env } from '../utils';
+
+export class TorrentCatalogsPreset extends Preset {
+ static override get METADATA() {
+ const supportedResources = [constants.CATALOG_RESOURCE];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'Torrent Catalogs',
+ supportedResources,
+ Env.DEFAULT_TORRENT_CATALOGS_TIMEOUT
+ ).filter((option) => option.id !== 'url'),
+ ];
+
+ return {
+ ID: 'torrent-catalogs',
+ NAME: 'Torrent Catalogs',
+ LOGO: 'https://i.ibb.co/w4BnkC9/GwxAcDV.png',
+ URL: Env.TORRENT_CATALOGS_URL,
+ TIMEOUT: Env.DEFAULT_TORRENT_CATALOGS_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT:
+ Env.DEFAULT_TORRENT_CATALOGS_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: [],
+ DESCRIPTION:
+ 'Provides catalogs for movies/series/anime based on top seeded torrents. Requires Kitsu addon for anime.',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [],
+ SUPPORTED_RESOURCES: supportedResources,
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ return [this.generateAddon(userData, options)];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: options.name || this.METADATA.NAME,
+ manifestUrl: `${Env.TORRENT_CATALOGS_URL}/manifest.json`,
+ enabled: true,
+ library: false,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+}
diff --git a/packages/core/src/presets/torrentio.ts b/packages/core/src/presets/torrentio.ts
new file mode 100644
index 00000000..baba09e4
--- /dev/null
+++ b/packages/core/src/presets/torrentio.ts
@@ -0,0 +1,182 @@
+import { Addon, Option, UserData, Resource, Stream, ParsedStream } from '../db';
+import { Preset, baseOptions } from './preset';
+import { Env, SERVICE_DETAILS } from '../utils';
+import { constants, ServiceId } from '../utils';
+import { StreamParser } from '../parser';
+
+export class TorrentioParser extends StreamParser {
+ override getFolder(stream: Stream): string | undefined {
+ const description = stream.description || stream.title;
+ if (!description) {
+ return undefined;
+ }
+ const folderName = description.split('\n')[0];
+ return folderName;
+ }
+
+ protected override getLanguages(
+ stream: Stream,
+ currentParsedStream: ParsedStream
+ ): string[] {
+ if (stream.description?.includes('Multi Subs')) {
+ return [];
+ }
+ return super.getLanguages(stream, currentParsedStream);
+ }
+}
+
+export class TorrentioPreset extends Preset {
+ static override getParser(): typeof StreamParser {
+ return TorrentioParser;
+ }
+
+ static override get METADATA() {
+ const supportedServices: ServiceId[] = [
+ constants.REALDEBRID_SERVICE,
+ constants.PREMIUMIZE_SERVICE,
+ constants.ALLEDEBRID_SERVICE,
+ constants.TORBOX_SERVICE,
+ constants.EASYDEBRID_SERVICE,
+ constants.PUTIO_SERVICE,
+ constants.DEBRIDLINK_SERVICE,
+ constants.OFFCLOUD_SERVICE,
+ ];
+ const supportedResources = [
+ constants.STREAM_RESOURCE,
+ constants.CATALOG_RESOURCE,
+ constants.META_RESOURCE,
+ ];
+
+ const options: Option[] = [
+ ...baseOptions(
+ 'Torrentio',
+ supportedResources,
+ Env.DEFAULT_TORRENTIO_TIMEOUT
+ ),
+ {
+ id: 'services',
+ name: 'Services',
+ description:
+ 'Optionally override the services that are used. If not specified, then the services that are enabled and supported will be used.',
+ type: 'multi-select',
+ required: false,
+ options: supportedServices.map((service) => ({
+ value: service,
+ label: constants.SERVICE_DETAILS[service].name,
+ })),
+ default: undefined,
+ emptyIsUndefined: true,
+ },
+ {
+ id: 'useMultipleInstances',
+ name: 'Use Multiple Instances',
+ description:
+ 'When using multiple services, use a different Torrentio addon for each service, rather than using one instance for all services',
+ type: 'boolean',
+ default: false,
+ required: true,
+ },
+ ];
+
+ return {
+ ID: 'torrentio',
+ NAME: 'Torrentio',
+ LOGO: `${Env.TORRENTIO_URL}/images/logo_v1.png`,
+ URL: Env.TORRENTIO_URL,
+ TIMEOUT: Env.DEFAULT_TORRENTIO_TIMEOUT || Env.DEFAULT_TIMEOUT,
+ USER_AGENT: Env.DEFAULT_TORRENTIO_USER_AGENT || Env.DEFAULT_USER_AGENT,
+ SUPPORTED_SERVICES: supportedServices,
+ REQUIRES_SERVICE: false,
+ DESCRIPTION:
+ 'Provides torrent streams from a multitude of providers and has debrid support.',
+ OPTIONS: options,
+ SUPPORTED_STREAM_TYPES: [
+ constants.P2P_STREAM_TYPE,
+ constants.DEBRID_STREAM_TYPE,
+ ],
+ SUPPORTED_RESOURCES: [
+ constants.STREAM_RESOURCE,
+ constants.META_RESOURCE,
+ constants.CATALOG_RESOURCE,
+ ],
+ };
+ }
+
+ static async generateAddons(
+ userData: UserData,
+ options: Record
+ ): Promise {
+ // baseUrl can either be something like https://torrentio.com/ or it can be a custom manifest url.
+ // if it is a custom manifest url, return a single addon with the custom manifest url.
+ if (options?.url?.endsWith('/manifest.json')) {
+ return [this.generateAddon(userData, options, [])];
+ }
+
+ const usableServices = this.getUsableServices(userData, options.services);
+
+ // if no services are usable, return a single addon with no services
+ if (!usableServices || usableServices.length === 0) {
+ return [this.generateAddon(userData, options, [])];
+ }
+
+ // if user has specified useMultipleInstances, return a single addon for each service
+ if (options?.useMultipleInstances) {
+ return usableServices.map((service) =>
+ this.generateAddon(userData, options, [service.id])
+ );
+ }
+
+ // return a single addon with all usable services
+ return [
+ this.generateAddon(
+ userData,
+ options,
+ usableServices.map((service) => service.id)
+ ),
+ ];
+ }
+
+ private static generateAddon(
+ userData: UserData,
+ options: Record,
+ services: ServiceId[]
+ ): Addon {
+ return {
+ name: options.name || this.METADATA.NAME,
+ identifyingName: `${options.name || this.METADATA.NAME} ${services.map((id) => constants.SERVICE_DETAILS[id].shortName).join(' | ')}`,
+ manifestUrl: this.generateManifestUrl(userData, services, options.url),
+ enabled: true,
+ resources: options.resources || this.METADATA.SUPPORTED_RESOURCES,
+ timeout: options.timeout || this.METADATA.TIMEOUT,
+ fromPresetId: this.METADATA.ID,
+ headers: {
+ 'User-Agent': this.METADATA.USER_AGENT,
+ },
+ };
+ }
+
+ private static generateManifestUrl(
+ userData: UserData,
+ services: ServiceId[],
+ url?: string
+ ) {
+ url = url || this.METADATA.URL;
+ if (url.endsWith('/manifest.json')) {
+ return url;
+ }
+
+ const configString = services.length
+ ? this.urlEncodeKeyValuePairs(
+ services.map((service) => [
+ service,
+ this.getServiceCredential(service, userData, {
+ [constants.PUTIO_SERVICE]: (credentials: any) =>
+ `${credentials.clientId}@${credentials.token}`,
+ }),
+ ])
+ )
+ : '';
+
+ return `${url}${configString ? '/' + configString : ''}/manifest.json`;
+ }
+}
diff --git a/packages/core/src/proxy/base.ts b/packages/core/src/proxy/base.ts
new file mode 100644
index 00000000..4d805255
--- /dev/null
+++ b/packages/core/src/proxy/base.ts
@@ -0,0 +1,132 @@
+import { StreamProxyConfig } from '../db';
+import { Cache, createLogger, maskSensitiveInfo, Env } from '../utils';
+
+const logger = createLogger('proxy');
+const cache = Cache.getInstance('publicIp');
+
+export interface ProxyStream {
+ url: string;
+ filename?: string;
+ headers?: {
+ request?: Record;
+ response?: Record;
+ };
+}
+
+type ValidatedStreamProxyConfig = StreamProxyConfig & {
+ id: 'mediaflow' | 'stremthru';
+ url: string;
+ credentials: string;
+};
+
+export abstract class BaseProxy {
+ protected readonly config: ValidatedStreamProxyConfig;
+ private readonly PRIVATE_CIDR =
+ /^(10\.|127\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)/;
+
+ constructor(config: StreamProxyConfig) {
+ if (!config.id || !config.credentials || !config.url) {
+ throw new Error('Proxy configuration is missing');
+ }
+
+ this.config = {
+ enabled: config.enabled ?? false,
+ id: config.id,
+ url: config.url,
+ credentials: config.credentials,
+ publicIp: config.publicIp,
+ proxiedAddons: config.proxiedAddons,
+ proxiedServices: config.proxiedServices,
+ };
+ }
+
+ public getConfig(): StreamProxyConfig {
+ return this.config;
+ }
+
+ protected abstract generateProxyUrl(endpoint: string): URL;
+ protected abstract getPublicIpEndpoint(): string;
+ protected abstract getPublicIpFromResponse(data: any): string | null;
+ protected abstract generateStreamUrls(
+ streams: ProxyStream[]
+ ): Promise;
+
+ public async getPublicIp(): Promise {
+ if (!this.config.url) {
+ logger.error('Proxy URL is missing');
+ throw new Error('Proxy URL is missing');
+ }
+
+ if (this.config.publicIp) {
+ return this.config.publicIp;
+ }
+
+ const proxyUrl = new URL(this.config.url.replace(/\/$/, ''));
+ if (this.PRIVATE_CIDR.test(proxyUrl.hostname)) {
+ logger.error('Proxy URL is a private IP address, returning null');
+ return null;
+ }
+
+ const cacheKey = `${this.config.id}:${this.config.url}:${this.config.credentials}`;
+ const cachedPublicIp = cache ? cache.get(cacheKey) : null;
+ if (cachedPublicIp) {
+ logger.debug('Returning cached public IP');
+ return cachedPublicIp;
+ }
+
+ const ipUrl = this.generateProxyUrl(this.getPublicIpEndpoint());
+
+ if (Env.LOG_SENSITIVE_INFO) {
+ logger.debug(`GET ${ipUrl.toString()}`);
+ } else {
+ logger.debug(
+ `GET ${ipUrl.protocol}://${maskSensitiveInfo(ipUrl.hostname)}${ipUrl.port ? `:${ipUrl.port}` : ''}${ipUrl.pathname}`
+ );
+ }
+
+ const response = await fetch(ipUrl.toString(), {
+ method: 'GET',
+ headers: this.getHeaders(),
+ signal: AbortSignal.timeout(30000), // 30 second timeout
+ });
+
+ if (!response.ok) {
+ throw new Error(`${response.status}: ${response.statusText}`);
+ }
+
+ const data = await response.json();
+ const publicIp = this.getPublicIpFromResponse(data);
+
+ if (publicIp && cache) {
+ cache.set(cacheKey, publicIp, 900); // 15 minute cache
+ } else {
+ logger.error(
+ `Proxy did not respond with a public IP. Response: ${JSON.stringify(data)}`
+ );
+ throw new Error('Proxy did not respond with a public IP');
+ }
+
+ return publicIp;
+ }
+
+ protected abstract getHeaders(): Record;
+
+ public async generateUrls(streams: ProxyStream[]): Promise {
+ if (!streams.length) {
+ return [];
+ }
+
+ if (!this.config) {
+ throw new Error('Proxy configuration is missing');
+ }
+
+ try {
+ return await this.generateStreamUrls(streams);
+ } catch (error) {
+ logger.error(
+ `Failed to generate proxy URLs: ${error instanceof Error ? error.message : String(error)}`
+ );
+ return null;
+ }
+ }
+}
diff --git a/packages/core/src/proxy/index.ts b/packages/core/src/proxy/index.ts
new file mode 100644
index 00000000..919b6741
--- /dev/null
+++ b/packages/core/src/proxy/index.ts
@@ -0,0 +1,20 @@
+export * from './base';
+export * from './mediaflow';
+export * from './stremthru';
+
+import { constants } from '../utils';
+import { BaseProxy } from './base';
+import { MediaFlowProxy } from './mediaflow';
+import { StremThruProxy } from './stremthru';
+import { StreamProxyConfig } from '../db';
+
+export function createProxy(config: StreamProxyConfig): BaseProxy {
+ switch (config.id) {
+ case constants.MEDIAFLOW_SERVICE:
+ return new MediaFlowProxy(config);
+ case constants.STREMTHRU_SERVICE:
+ return new StremThruProxy(config);
+ default:
+ throw new Error(`Unknown proxy type: ${config.id}`);
+ }
+}
diff --git a/packages/core/src/proxy/mediaflow.ts b/packages/core/src/proxy/mediaflow.ts
new file mode 100644
index 00000000..149dbb44
--- /dev/null
+++ b/packages/core/src/proxy/mediaflow.ts
@@ -0,0 +1,93 @@
+import { BaseProxy, ProxyStream } from './base';
+import { createLogger, maskSensitiveInfo, Env } from '../utils';
+import path from 'path';
+
+const logger = createLogger('mediaflow');
+
+export class MediaFlowProxy extends BaseProxy {
+ protected generateProxyUrl(endpoint: string): URL {
+ const proxyUrl = new URL(this.config.url.replace(/\/$/, ''));
+ proxyUrl.pathname = `${proxyUrl.pathname === '/' ? '' : proxyUrl.pathname}${endpoint}`;
+ if (endpoint === '/proxy/ip') {
+ proxyUrl.searchParams.set('api_password', this.config.credentials);
+ }
+ return proxyUrl;
+ }
+
+ protected getPublicIpEndpoint(): string {
+ return '/proxy/ip';
+ }
+
+ protected getPublicIpFromResponse(data: any): string | null {
+ return data.ip || null;
+ }
+
+ protected getHeaders(): Record {
+ return {
+ 'Content-Type': 'application/json',
+ };
+ }
+
+ protected async generateStreamUrls(
+ streams: ProxyStream[]
+ ): Promise {
+ const proxyUrl = this.generateProxyUrl('/generate_urls');
+
+ const data = {
+ mediaflow_proxy_url: this.config.url.replace(/\/$/, ''),
+ api_password: Env.ENCRYPT_MEDIAFLOW_URLS
+ ? this.config.credentials
+ : undefined,
+ urls: streams.map((stream) => ({
+ endpoint: '/proxy/stream',
+ filename: stream.filename || path.basename(stream.url),
+ query_params: Env.ENCRYPT_MEDIAFLOW_URLS
+ ? undefined
+ : {
+ api_password: this.config.credentials,
+ },
+ destination_url: stream.url,
+ request_headers: stream.headers?.request,
+ response_headers: stream.headers?.response,
+ })),
+ };
+
+ if (Env.LOG_SENSITIVE_INFO) {
+ logger.debug(`POST ${proxyUrl.toString()}`);
+ } else {
+ logger.debug(
+ `POST ${proxyUrl.protocol}://${maskSensitiveInfo(proxyUrl.hostname)}${proxyUrl.port ? `:${proxyUrl.port}` : ''}/generate_urls`
+ );
+ }
+
+ const response = await fetch(proxyUrl.toString(), {
+ method: 'POST',
+ headers: this.getHeaders(),
+ body: JSON.stringify(data),
+ signal: AbortSignal.timeout(30000),
+ });
+
+ if (!response.ok) {
+ throw new Error(`${response.status}: ${response.statusText}`);
+ }
+
+ let responseData: any;
+ try {
+ responseData = await response.json();
+ } catch (error) {
+ const text = await response.text();
+ logger.debug(`Response body: ${text}`);
+ throw new Error('Failed to parse JSON response from MediaFlow');
+ }
+
+ if (responseData.error) {
+ throw new Error(responseData.error);
+ }
+
+ if (responseData.urls) {
+ return responseData.urls;
+ } else {
+ throw new Error('No URLs were returned from MediaFlow');
+ }
+ }
+}
diff --git a/packages/core/src/proxy/stremthru.ts b/packages/core/src/proxy/stremthru.ts
new file mode 100644
index 00000000..a66c3c57
--- /dev/null
+++ b/packages/core/src/proxy/stremthru.ts
@@ -0,0 +1,98 @@
+import { BaseProxy, ProxyStream } from './base';
+import { createLogger, maskSensitiveInfo, Env } from '../utils';
+
+const logger = createLogger('stremthru');
+
+export class StremThruProxy extends BaseProxy {
+ protected generateProxyUrl(endpoint: string): URL {
+ const proxyUrl = new URL(this.config.url.replace(/\/$/, ''));
+ proxyUrl.pathname = `${proxyUrl.pathname === '/' ? '' : proxyUrl.pathname}${endpoint}`;
+ return proxyUrl;
+ }
+
+ protected getPublicIpEndpoint(): string {
+ return '/v0/health/__debug__';
+ }
+
+ protected getPublicIpFromResponse(data: any): string | null {
+ return typeof data.data?.ip?.exposed === 'object'
+ ? data.data.ip.exposed['*'] || data.data.ip.machine
+ : data.data?.ip?.machine || null;
+ }
+
+ protected getHeaders(): Record {
+ const headers: Record = {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ };
+
+ if (Env.ENCRYPT_STREMTHRU_URLS) {
+ headers['X-StremThru-Authorization'] = `Basic ${this.config.credentials}`;
+ }
+
+ return headers;
+ }
+
+ protected async generateStreamUrls(
+ streams: ProxyStream[]
+ ): Promise {
+ const proxyUrl = this.generateProxyUrl('/v0/proxy');
+
+ if (!Env.ENCRYPT_STREMTHRU_URLS) {
+ proxyUrl.searchParams.set('token', this.config.credentials);
+ }
+
+ const data = new URLSearchParams();
+
+ streams.forEach((stream, i) => {
+ data.append('url', stream.url);
+ let req_headers = '';
+ if (stream.headers?.request) {
+ for (const [key, value] of Object.entries(stream.headers.request)) {
+ req_headers += `${key}: ${value}\n`;
+ }
+ }
+ data.append(`req_headers[${i}]`, req_headers);
+ if (stream.filename) {
+ data.append(`filename[${i}]`, stream.filename);
+ }
+ });
+
+ if (Env.LOG_SENSITIVE_INFO) {
+ logger.debug(`POST ${proxyUrl.toString()}`);
+ } else {
+ logger.debug(
+ `POST ${proxyUrl.protocol}://${maskSensitiveInfo(proxyUrl.hostname)}${proxyUrl.port ? `:${proxyUrl.port}` : ''}/v0/proxy`
+ );
+ }
+
+ const response = await fetch(proxyUrl.toString(), {
+ method: 'POST',
+ headers: this.getHeaders(),
+ body: data,
+ signal: AbortSignal.timeout(30000),
+ });
+
+ if (!response.ok) {
+ throw new Error(`${response.status}: ${response.statusText}`);
+ }
+
+ let responseData: any;
+ try {
+ responseData = await response.json();
+ } catch (error) {
+ const text = await response.text();
+ logger.debug(`Response body: ${text}`);
+ throw new Error('Failed to parse JSON response from StremThru');
+ }
+
+ if (responseData.error) {
+ throw new Error(responseData.error);
+ }
+
+ if (responseData.data?.items) {
+ return responseData.data.items;
+ } else {
+ throw new Error('No URLs were returned from StremThru');
+ }
+ }
+}
diff --git a/packages/core/src/transformers/index.ts b/packages/core/src/transformers/index.ts
new file mode 100644
index 00000000..176ced25
--- /dev/null
+++ b/packages/core/src/transformers/index.ts
@@ -0,0 +1 @@
+export * from './stremio';
diff --git a/packages/core/src/transformers/stremio.ts b/packages/core/src/transformers/stremio.ts
new file mode 100644
index 00000000..69b4d154
--- /dev/null
+++ b/packages/core/src/transformers/stremio.ts
@@ -0,0 +1,325 @@
+import { constants, Env } from '..';
+import {
+ Meta,
+ MetaPreview,
+ ParsedStream,
+ Resource,
+ AIOStream,
+ Subtitle,
+ UserData,
+ AddonCatalog,
+ Stream,
+ AddonCatalogResponse,
+ AIOStreamResponse,
+ SubtitleResponse,
+ MetaResponse,
+ CatalogResponse,
+ StreamResponse,
+} from '../db';
+import { createFormatter } from '../formatters';
+import { AIOStreamsError, AIOStreamsResponse } from '../main';
+import { createLogger } from '../utils';
+
+type ErrorOptions = {
+ errorTitle?: string;
+ errorDescription?: string;
+ errorUrl?: string;
+};
+
+const logger = createLogger('stremio');
+
+export class StremioTransformer {
+ constructor(private readonly userData: UserData) {}
+
+ public showError(resource: Resource, errors: AIOStreamsError[]) {
+ if (
+ errors.length > 0 &&
+ !this.userData.hideErrors &&
+ !this.userData.hideErrorsForResources?.includes(resource)
+ ) {
+ return true;
+ }
+ return false;
+ }
+
+ async transformStreams(
+ response: AIOStreamsResponse
+ ): Promise {
+ const { data: streams, errors } = response;
+
+ let transformedStreams: AIOStream[] = [];
+
+ let formatter;
+ if (this.userData.formatter.id === constants.CUSTOM_FORMATTER) {
+ const template = this.userData.formatter.definition;
+ if (!template) {
+ throw new Error('No template defined for custom formatter');
+ }
+ formatter = createFormatter(
+ this.userData.formatter.id,
+ template,
+ this.userData.addonName
+ );
+ } else {
+ formatter = createFormatter(
+ this.userData.formatter.id,
+ undefined,
+ this.userData.addonName
+ );
+ }
+
+ logger.info(
+ `Transforming ${streams.length} streams, using formatter ${this.userData.formatter.id}`
+ );
+
+ transformedStreams = await Promise.all(
+ streams.map(async (stream: ParsedStream): Promise => {
+ const { name, description } = stream.addon.streamPassthrough
+ ? {
+ name: stream.originalName,
+ description: stream.originalDescription,
+ }
+ : formatter.format(stream);
+ const identifyingAttributes = [
+ stream.parsedFile?.resolution,
+ stream.parsedFile?.quality,
+ stream.parsedFile?.encode,
+ stream.parsedFile?.audioTags,
+ stream.parsedFile?.visualTags,
+ stream.parsedFile?.languages,
+ stream.parsedFile?.releaseGroup,
+ stream.indexer,
+ ].filter(Boolean);
+ const bingeGroup = `${stream.proxied ? 'proxied.' : ''}${identifyingAttributes.join('|')}`;
+ return {
+ name,
+ description,
+ url: ['http', 'usenet', 'debrid', 'live'].includes(stream.type)
+ ? stream.url
+ : undefined,
+ infoHash:
+ stream.type === 'p2p' ? stream.torrent?.infoHash : undefined,
+ ytId: stream.type === 'youtube' ? stream.ytId : undefined,
+ externalUrl:
+ stream.type === 'external' ? stream.externalUrl : undefined,
+ sources: stream.type === 'p2p' ? stream.torrent?.sources : undefined,
+ subtitles: stream.subtitles,
+ behaviorHints: {
+ countryWhitelist: stream.countryWhitelist,
+ notWebReady: stream.notWebReady,
+ bingeGroup: bingeGroup,
+ proxyHeaders:
+ stream.requestHeaders || stream.responseHeaders
+ ? {
+ request: stream.requestHeaders,
+ response: stream.responseHeaders,
+ }
+ : undefined,
+ videoHash: stream.videoHash,
+ videoSize: stream.size,
+ filename: stream.filename,
+ },
+ streamData: {
+ type: stream.type,
+ proxied: stream.proxied,
+ indexer: stream.indexer,
+ age: stream.age,
+ duration: stream.duration,
+ library: stream.library,
+ size: stream.size,
+ folderSize: stream.folderSize,
+ torrent: stream.torrent,
+ addon: stream.addon.name,
+ filename: stream.filename,
+ folderName: stream.folderName,
+ service: stream.service,
+ parsedFile: stream.parsedFile,
+ message: stream.message,
+ regexMatched: stream.regexMatched,
+ keywordMatched: stream.keywordMatched,
+ },
+ };
+ })
+ );
+
+ // add errors to the end (if this.userData.hideErrors is false or the resource is not in this.userData.hideErrorsForResources)
+ if (this.showError('stream', errors)) {
+ transformedStreams.push(
+ ...errors.map((error) =>
+ StremioTransformer.createErrorStream({
+ errorTitle: error.title,
+ errorDescription: error.description,
+ })
+ )
+ );
+ }
+
+ return {
+ streams: transformedStreams,
+ };
+ }
+
+ transformSubtitles(
+ response: AIOStreamsResponse
+ ): SubtitleResponse {
+ const { data: subtitles, errors } = response;
+
+ if (this.showError('subtitles', errors)) {
+ subtitles.push(
+ ...errors.map((error) =>
+ StremioTransformer.createErrorSubtitle({
+ errorTitle: error.title,
+ errorDescription: error.description,
+ })
+ )
+ );
+ }
+
+ return {
+ subtitles,
+ };
+ }
+
+ transformCatalog(
+ response: AIOStreamsResponse
+ ): CatalogResponse {
+ const { data: metas, errors } = response;
+
+ if (this.showError('catalog', errors)) {
+ metas.push(
+ ...errors.map((error) =>
+ StremioTransformer.createErrorMeta({
+ errorTitle: error.title,
+ errorDescription: error.description,
+ })
+ )
+ );
+ }
+
+ return {
+ metas,
+ };
+ }
+
+ transformMeta(response: AIOStreamsResponse): MetaResponse {
+ const { data: meta, errors } = response;
+
+ if (this.showError('meta', errors) || !meta) {
+ return {
+ meta: StremioTransformer.createErrorMeta({
+ errorTitle: errors.length > 0 ? errors[0].title : undefined,
+ errorDescription: errors[0]?.description || 'Unknown error',
+ }),
+ };
+ }
+ return {
+ meta,
+ };
+ }
+
+ transformAddonCatalog(
+ response: AIOStreamsResponse
+ ): AddonCatalogResponse {
+ const { data: addonCatalogs, errors } = response;
+ if (this.showError('addon_catalog', errors)) {
+ addonCatalogs.push(
+ ...errors.map((error) =>
+ StremioTransformer.createErrorAddonCatalog({
+ errorTitle: error.title,
+ errorDescription: error.description,
+ })
+ )
+ );
+ }
+ return {
+ addons: addonCatalogs,
+ };
+ }
+ static createErrorStream(options: ErrorOptions = {}): AIOStream {
+ const {
+ errorTitle = `[❌] ${Env.ADDON_NAME}`,
+ errorDescription = 'Unknown error',
+ errorUrl = 'https://github.com/Viren070/AIOStreams',
+ } = options;
+ return {
+ name: errorTitle,
+ description: errorDescription,
+ externalUrl: errorUrl,
+ streamData: {
+ type: constants.ERROR_STREAM_TYPE,
+ error: {
+ title: errorTitle,
+ description: errorDescription,
+ },
+ },
+ };
+ }
+
+ static createErrorSubtitle(options: ErrorOptions = {}) {
+ const {
+ errorTitle = 'Unknown error',
+ errorDescription = 'Unknown error',
+ errorUrl = 'https://github.com/Viren070/AIOStreams',
+ } = options;
+ return {
+ id: `error.${errorTitle}`,
+ lang: `[❌] ${errorTitle} - ${errorDescription}`,
+ url: errorUrl,
+ };
+ }
+
+ static createErrorMeta(options: ErrorOptions = {}): MetaPreview {
+ const {
+ errorTitle = `[❌] ${Env.ADDON_NAME} - Error`,
+ errorDescription = 'Unknown error',
+ } = options;
+ return {
+ id: `error.${errorTitle}`,
+ name: errorTitle,
+ description: errorDescription,
+ type: 'movie',
+ };
+ }
+
+ static createErrorAddonCatalog(options: ErrorOptions = {}): AddonCatalog {
+ const {
+ errorTitle = `[❌] ${Env.ADDON_NAME} - Error`,
+ errorDescription = 'Unknown error',
+ } = options;
+ return {
+ transportName: 'http',
+ transportUrl: 'https://github.com/Viren070/AIOStreams',
+ manifest: {
+ name: errorTitle,
+ description: errorDescription,
+ id: `error.${errorTitle}`,
+ version: '1.0.0',
+ types: ['addon_catalog'],
+ resources: [{ name: 'addon_catalog', types: ['addon_catalog'] }],
+ catalogs: [],
+ },
+ };
+ }
+
+ static createDynamicError(
+ resource: Resource,
+ options: ErrorOptions = {}
+ ): any {
+ if (resource === 'meta') {
+ return { meta: StremioTransformer.createErrorMeta(options) };
+ }
+ if (resource === 'addon_catalog') {
+ return { addons: [StremioTransformer.createErrorAddonCatalog(options)] };
+ }
+ if (resource === 'catalog') {
+ return { metas: [StremioTransformer.createErrorMeta(options)] };
+ }
+ if (resource === 'stream') {
+ return { streams: [StremioTransformer.createErrorStream(options)] };
+ }
+ if (resource === 'subtitles') {
+ return { subtitles: [StremioTransformer.createErrorSubtitle(options)] };
+ }
+ return null;
+ }
+}
diff --git a/packages/utils/src/cache.ts b/packages/core/src/utils/cache.ts
similarity index 76%
rename from packages/utils/src/cache.ts
rename to packages/core/src/utils/cache.ts
index 7a907ea9..f6ba031c 100644
--- a/packages/utils/src/cache.ts
+++ b/packages/core/src/utils/cache.ts
@@ -1,5 +1,5 @@
import { createLogger } from './logger';
-import { Settings } from './settings';
+import { Env } from './env';
const logger = createLogger('cache');
@@ -28,7 +28,7 @@ export class Cache {
*/
public static getInstance(
name: string,
- maxSize: number = Settings.MAX_CACHE_SIZE
+ maxSize: number = Env.MAX_CACHE_SIZE
): Cache {
if (!this.instances.has(name)) {
logger.debug(`Creating new cache instance: ${name}`);
@@ -48,22 +48,22 @@ export class Cache {
* @param ttl Time-To-Live in seconds for the cached value
* @param args The arguments to pass to the function
*/
- wrap any>(
+ async wrap any>(
fn: T,
key: K,
ttl: number,
...args: Parameters
- ): ReturnType {
+ ): Promise> {
const cachedValue = this.get(key);
if (cachedValue !== undefined) {
return cachedValue as ReturnType;
}
- const result = fn(...args);
+ const result = await fn(...args);
this.set(key, result, ttl);
return result;
}
- get(key: K): V | undefined {
+ get(key: K, updateTTL: boolean = true): V | undefined {
const item = this.cache.get(key);
if (item) {
const now = Date.now();
@@ -71,12 +71,20 @@ export class Cache {
this.cache.delete(key);
return undefined;
}
- item.lastAccessed = now;
+ if (updateTTL) {
+ item.lastAccessed = now;
+ }
return item.value;
}
return undefined;
}
+ /**
+ * Set a value in the cache with a specific TTL
+ * @param key The key to set the value for
+ * @param value The value to set
+ * @param ttl The TTL in seconds
+ */
set(key: K, value: V, ttl: number): void {
if (this.cache.size >= this.maxSize) {
this.evict();
@@ -84,6 +92,18 @@ export class Cache {
this.cache.set(key, new CacheItem(value, Date.now(), ttl * 1000));
}
+ /**
+ * Update the value of an existing key in the cache without changing the TTL
+ * @param key The key to update
+ * @param value The new value
+ */
+ update(key: K, value: V): void {
+ const item = this.cache.get(key);
+ if (item) {
+ item.value = value;
+ }
+ }
+
clear(): void {
this.cache.clear();
}
diff --git a/packages/core/src/utils/config.ts b/packages/core/src/utils/config.ts
new file mode 100644
index 00000000..e6df148b
--- /dev/null
+++ b/packages/core/src/utils/config.ts
@@ -0,0 +1,625 @@
+import {
+ UserData,
+ UserDataSchema,
+ PresetObject,
+ Service,
+ Option,
+ StreamProxyConfig,
+ Group,
+} from '../db/schemas';
+import { AIOStreams } from '../main';
+import { Preset, PresetManager } from '../presets';
+import { createProxy } from '../proxy';
+import { constants } from '.';
+import { isEncrypted, decryptString, encryptString } from './crypto';
+import { Env } from './env';
+import { createLogger, maskSensitiveInfo } from './logger';
+import { ZodError } from 'zod';
+import { ConditionParser } from '../parser/conditions';
+import { RPDB } from './rpdb';
+import { FeatureControl } from './feature';
+import { compileRegex } from './regex';
+
+const logger = createLogger('core');
+
+export const formatZodError = (error: ZodError) => {
+ let errs = [];
+ for (const issue of error.issues) {
+ errs.push(`Invalid value for ${issue.path.join('.')}: ${issue.message}`);
+ }
+ return errs.join(' | ');
+};
+
+function getServiceCredentialDefault(
+ serviceId: constants.ServiceId,
+ credentialId: string
+) {
+ // env mapping
+ switch (serviceId) {
+ case constants.REALDEBRID_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.DEFAULT_REALDEBRID_API_KEY;
+ }
+ break;
+ case constants.ALLEDEBRID_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.DEFAULT_ALLDEBRID_API_KEY;
+ }
+ break;
+ case constants.PREMIUMIZE_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.DEFAULT_PREMIUMIZE_API_KEY;
+ }
+ break;
+ case constants.DEBRIDLINK_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.DEFAULT_DEBRIDLINK_API_KEY;
+ }
+ break;
+ case constants.TORBOX_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.DEFAULT_TORBOX_API_KEY;
+ }
+ break;
+ case constants.EASYDEBRID_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.DEFAULT_EASYDEBRID_API_KEY;
+ }
+ break;
+ case constants.PUTIO_SERVICE:
+ switch (credentialId) {
+ case 'clientId':
+ return Env.DEFAULT_PUTIO_CLIENT_ID;
+ case 'clientSecret':
+ return Env.DEFAULT_PUTIO_CLIENT_SECRET;
+ }
+ break;
+ case constants.PIKPAK_SERVICE:
+ switch (credentialId) {
+ case 'email':
+ return Env.DEFAULT_PIKPAK_EMAIL;
+ case 'password':
+ return Env.DEFAULT_PIKPAK_PASSWORD;
+ }
+ break;
+ case constants.OFFCLOUD_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.DEFAULT_OFFCLOUD_API_KEY;
+ case 'email':
+ return Env.DEFAULT_OFFCLOUD_EMAIL;
+ case 'password':
+ return Env.DEFAULT_OFFCLOUD_PASSWORD;
+ }
+ break;
+ case constants.SEEDR_SERVICE:
+ switch (credentialId) {
+ case 'encodedToken':
+ return Env.DEFAULT_SEEDR_ENCODED_TOKEN;
+ }
+ break;
+ case constants.EASYNEWS_SERVICE:
+ switch (credentialId) {
+ case 'username':
+ return Env.DEFAULT_EASYNEWS_USERNAME;
+ case 'password':
+ return Env.DEFAULT_EASYNEWS_PASSWORD;
+ }
+ break;
+ default:
+ return null;
+ }
+}
+
+function getServiceCredentialForced(
+ serviceId: constants.ServiceId,
+ credentialId: string
+) {
+ // env mapping
+ switch (serviceId) {
+ case constants.REALDEBRID_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.FORCED_REALDEBRID_API_KEY;
+ }
+ break;
+ case constants.ALLEDEBRID_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.FORCED_ALLDEBRID_API_KEY;
+ }
+ break;
+ case constants.PREMIUMIZE_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.FORCED_PREMIUMIZE_API_KEY;
+ }
+ break;
+ case constants.DEBRIDLINK_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.FORCED_DEBRIDLINK_API_KEY;
+ }
+ break;
+ case constants.TORBOX_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.FORCED_TORBOX_API_KEY;
+ }
+ break;
+ case constants.EASYDEBRID_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.FORCED_EASYDEBRID_API_KEY;
+ }
+ break;
+ case constants.PUTIO_SERVICE:
+ switch (credentialId) {
+ case 'clientId':
+ return Env.FORCED_PUTIO_CLIENT_ID;
+ case 'clientSecret':
+ return Env.FORCED_PUTIO_CLIENT_SECRET;
+ }
+ break;
+ case constants.PIKPAK_SERVICE:
+ switch (credentialId) {
+ case 'email':
+ return Env.FORCED_PIKPAK_EMAIL;
+ case 'password':
+ return Env.FORCED_PIKPAK_PASSWORD;
+ }
+ break;
+ case constants.OFFCLOUD_SERVICE:
+ switch (credentialId) {
+ case 'apiKey':
+ return Env.FORCED_OFFCLOUD_API_KEY;
+ case 'email':
+ return Env.FORCED_OFFCLOUD_EMAIL;
+ case 'password':
+ return Env.FORCED_OFFCLOUD_PASSWORD;
+ }
+ break;
+ case constants.SEEDR_SERVICE:
+ switch (credentialId) {
+ case 'encodedToken':
+ return Env.FORCED_SEEDR_ENCODED_TOKEN;
+ }
+ break;
+ case constants.EASYNEWS_SERVICE:
+ switch (credentialId) {
+ case 'username':
+ return Env.FORCED_EASYNEWS_USERNAME;
+ case 'password':
+ return Env.FORCED_EASYNEWS_PASSWORD;
+ }
+ break;
+ default:
+ return null;
+ }
+}
+
+export function getEnvironmentServiceDetails(): typeof constants.SERVICE_DETAILS {
+ return Object.fromEntries(
+ Object.entries(constants.SERVICE_DETAILS)
+ .filter(([id, _]) => !FeatureControl.disabledServices.has(id))
+ .map(([id, service]) => [
+ id as constants.ServiceId,
+ {
+ id: service.id,
+ name: service.name,
+ shortName: service.shortName,
+ knownNames: service.knownNames,
+ signUpText: service.signUpText,
+ credentials: service.credentials.map((cred) => ({
+ id: cred.id,
+ name: cred.name,
+ description: cred.description,
+ type: cred.type,
+ required: cred.required,
+ default: getServiceCredentialDefault(service.id, cred.id)
+ ? encryptString(getServiceCredentialDefault(service.id, cred.id)!)
+ .data
+ : null,
+ forced: getServiceCredentialForced(service.id, cred.id)
+ ? encryptString(getServiceCredentialForced(service.id, cred.id)!)
+ .data
+ : null,
+ })),
+ },
+ ])
+ ) as typeof constants.SERVICE_DETAILS;
+}
+
+export async function validateConfig(
+ data: any,
+ skipErrorsFromAddonsOrProxies: boolean = false,
+ decryptValues: boolean = false
+): Promise