From 0cb90645cd16f7559762c8677b5516475a0604e0 Mon Sep 17 00:00:00 2001
From: ArabCoders
Date: Thu, 27 Feb 2025 14:09:11 +0300
Subject: [PATCH 01/10] display portrait image in more clean way
---
ui/assets/css/style.css | 5 +++++
ui/components/History.vue | 8 ++++++--
ui/components/Queue.vue | 5 +++--
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/ui/assets/css/style.css b/ui/assets/css/style.css
index 95632bdd..20e9fd69 100644
--- a/ui/assets/css/style.css
+++ b/ui/assets/css/style.css
@@ -249,3 +249,8 @@ hr {
.play-active {
opacity: 1;
}
+
+.image-portrait {
+ object-fit: cover;
+ object-position: top;
+}
diff --git a/ui/components/History.vue b/ui/components/History.vue
index d3008801..b5aab95d 100644
--- a/ui/components/History.vue
+++ b/ui/components/History.vue
@@ -99,11 +99,13 @@
-
+
pImg(e)" :src="'/api/thumbnail?url=' + encodePath(item.extras.thumbnail)"
+ v-if="item.extras?.thumbnail" />
-
+
pImg(e)" v-if="item.extras?.thumbnail"
+ :src="'/api/thumbnail?url=' + encodePath(item.extras.thumbnail)" />
@@ -473,4 +475,6 @@ const reQueueItem = item => {
template: item.template,
})
}
+
+const pImg = e => e.target.naturalHeight > e.target.naturalWidth ? e.target.classList.add('image-portrait') : null
diff --git a/ui/components/Queue.vue b/ui/components/Queue.vue
index db3498e8..4ae417e8 100644
--- a/ui/components/Queue.vue
+++ b/ui/components/Queue.vue
@@ -53,8 +53,7 @@
-
+
@@ -274,4 +273,6 @@ const cancelItems = item => {
items.forEach(id => socket.emit('item_cancel', id));
}
+
+const pImg = e => e.target.naturalHeight > e.target.naturalWidth ? e.target.classList.add('image-portrait') : null
From c5924b02cc316e171e0abc46beaba5ddf9d48cb6 Mon Sep 17 00:00:00 2001
From: ArabCoders
Date: Thu, 27 Feb 2025 14:58:06 +0300
Subject: [PATCH 02/10] support format key in ytdlp.json, using the key will
ignore the selected preset.
---
app/library/DownloadQueue.py | 4 ++--
app/library/HttpAPI.py | 29 +++++++++++++++++++++++++++--
app/library/Utils.py | 6 +++++-
ui/components/NewDownload.vue | 35 +++++++++++++++++++++++++++++------
ui/components/TaskForm.vue | 35 ++++++++++++++++++++++++++++-------
ui/utils/index.js | 2 +-
6 files changed, 92 insertions(+), 19 deletions(-)
diff --git a/app/library/DownloadQueue.py b/app/library/DownloadQueue.py
index 10079d4e..fc718055 100644
--- a/app/library/DownloadQueue.py
+++ b/app/library/DownloadQueue.py
@@ -395,7 +395,7 @@ class DownloadQueue(metaclass=Singleton):
"func": lambda _, msg: logs.append(msg),
"level": logging.WARNING,
},
- **merge_config(self.config.ytdl_options, config),
+ **get_opts(preset, merge_config(self.config.ytdl_options, config)),
}
if cookies:
@@ -408,7 +408,7 @@ class DownloadQueue(metaclass=Singleton):
entry = await asyncio.wait_for(
fut=asyncio.get_running_loop().run_in_executor(
- None, extract_info, get_opts(preset, yt_conf), url, bool(self.config.ytdl_debug)
+ None, extract_info, yt_conf, url, bool(self.config.ytdl_debug)
),
timeout=self.config.extract_info_timeout,
)
diff --git a/app/library/HttpAPI.py b/app/library/HttpAPI.py
index e49453da..7369cf46 100644
--- a/app/library/HttpAPI.py
+++ b/app/library/HttpAPI.py
@@ -32,7 +32,15 @@ from .Playlist import Playlist
from .Segments import Segments
from .Subtitle import Subtitle
from .Tasks import Task, Tasks
-from .Utils import StreamingError, arg_converter, calc_download_path, get_video_info, validate_url, validate_uuid
+from .Utils import (
+ IGNORED_KEYS,
+ StreamingError,
+ arg_converter,
+ calc_download_path,
+ get_video_info,
+ validate_url,
+ validate_uuid,
+)
LOG = logging.getLogger("http_api")
MIME = magic.Magic(mime=True)
@@ -347,11 +355,28 @@ class HttpAPI(Common):
return web.json_response(data={"error": "args param is required."}, status=web.HTTPBadRequest.status_code)
try:
- return web.json_response(data=arg_converter(args), status=web.HTTPOk.status_code)
+ response = {"opts": {}, "output_template": None, "download_path": None}
+
+ data = arg_converter(args)
+
+ if "outtmpl" in data and "default" in data["outtmpl"]:
+ response["output_template"] = data["outtmpl"]["default"]
+
+ if "paths" in data and "home" in data["paths"]:
+ response["download_path"] = data["paths"]["home"]
+
+ for key in data:
+ if key in IGNORED_KEYS:
+ continue
+ if not key.startswith("_"):
+ response["opts"][key] = data[key]
+
+ return web.json_response(data=response, status=web.HTTPOk.status_code)
except Exception as e:
err = str(e).strip()
err = err.split("\n")[-1] if "\n" in err else err
LOG.error(f"Failed to convert args. '{err}'.")
+ LOG.exception(e)
return web.json_response(
data={"error": f"Failed to convert args. '{err}'."}, status=web.HTTPBadRequest.status_code
)
diff --git a/app/library/Utils.py b/app/library/Utils.py
index 078ec1c3..b8e3fe7d 100644
--- a/app/library/Utils.py
+++ b/app/library/Utils.py
@@ -23,7 +23,6 @@ IGNORED_KEYS: tuple[str] = (
"outtmpl",
"progress_hooks",
"postprocessor_hooks",
- "format",
"download_archive",
)
YTDLP_INFO_CLS: yt_dlp.YoutubeDL = None
@@ -45,6 +44,11 @@ def get_opts(preset: str, ytdl_opts: dict) -> dict:
ytdl extra options
"""
+ if "format" in ytdl_opts and len(ytdl_opts["format"]) > 2:
+ format = ytdl_opts["format"]
+ LOG.info(f"Format '{format}' was given via yt-dlp options. Therefore, the preset will be ignored.")
+ return ytdl_opts
+
opts = copy.deepcopy(ytdl_opts)
if "default" == preset:
diff --git a/ui/components/NewDownload.vue b/ui/components/NewDownload.vue
index 885989c5..8cf879ee 100644
--- a/ui/components/NewDownload.vue
+++ b/ui/components/NewDownload.vue
@@ -20,8 +20,9 @@
-
@@ -242,7 +245,15 @@ const convertOptions = async () => {
try {
convertInProgress.value = true
- ytdlpConfig.value = await convertCliOptions(ytdlpConfig.value)
+ const response = await convertCliOptions(ytdlpConfig.value)
+ ytdlpConfig.value = JSON.stringify(response.opts, null, 2)
+ if (response.output_template) {
+ output_template.value = response.output_template
+ }
+ if (response.download_path) {
+ downloadPath.value = response.download_path
+ }
+
} catch (e) {
toast.error(e.message)
} finally {
@@ -262,4 +273,16 @@ onUnmounted(() => {
socket.off('status', statusHandler)
socket.off('error', unlockDownload)
})
+
+const hasFormatInConfig = computed(() => {
+ if (!ytdlpConfig.value) {
+ return false
+ }
+ try {
+ const config = JSON.parse(ytdlpConfig.value)
+ return "format" in config
+ } catch (e) {
+ return false
+ }
+})
diff --git a/ui/components/TaskForm.vue b/ui/components/TaskForm.vue
index e625494f..338dbe53 100644
--- a/ui/components/TaskForm.vue
+++ b/ui/components/TaskForm.vue
@@ -32,7 +32,7 @@
@@ -69,7 +69,9 @@
-
+
@@ -79,7 +81,8 @@
- Select the preset to use for this URL.
+ Select the preset to use for this URL. The preset will be ignored if format key is present in
+ config.
@@ -138,8 +141,8 @@
Extends current global yt-dlp config with given options. Some fields are ignored like
- format cookiefile, paths, and outtmpl etc.
- Warning: Use with caution some of those options can break yt-dlp or the frontend.
+ cookiefile, paths, and outtmpl etc. Warning: Use with caution
+ some of those options can break yt-dlp or the frontend.
@@ -278,7 +281,14 @@ const convertOptions = async () => {
try {
convertInProgress.value = true
- form.config = await convertCliOptions(form.config)
+ const response = await convertCliOptions(form.config)
+ form.config = JSON.stringify(response.opts, null, 2)
+ if (response.output_template) {
+ form.template = response.output_template
+ }
+ if (response.download_path) {
+ form.folder = response.download_path
+ }
} catch (e) {
toast.error(e.message)
} finally {
@@ -286,4 +296,15 @@ const convertOptions = async () => {
}
}
+const hasFormatInConfig = computed(() => {
+ if (!form.config) {
+ return false
+ }
+ try {
+ const config = JSON.parse(form.config)
+ return "format" in config
+ } catch (e) {
+ return false
+ }
+})
diff --git a/ui/utils/index.js b/ui/utils/index.js
index 69cdfabc..47960e61 100644
--- a/ui/utils/index.js
+++ b/ui/utils/index.js
@@ -400,7 +400,7 @@ const convertCliOptions = async opts => {
throw new Error(`Error: (${response.status}): ${data.error}`)
}
- return JSON.stringify(data, null, 2)
+ return data
}
export {
From 259eae251a7c1d051a00580d95ce133d50ea067f Mon Sep 17 00:00:00 2001
From: ArabCoders
Date: Thu, 27 Feb 2025 15:30:52 +0300
Subject: [PATCH 03/10] initial work to support adding/deleting presets from
api
---
app/library/EventsSubscriber.py | 2 +
app/library/HttpAPI.py | 17 +++
app/library/Presets.py | 234 ++++++++++++++++++++++++++++++++
app/main.py | 2 +
4 files changed, 255 insertions(+)
create mode 100644 app/library/Presets.py
diff --git a/app/library/EventsSubscriber.py b/app/library/EventsSubscriber.py
index 2fb5a683..45d8b659 100644
--- a/app/library/EventsSubscriber.py
+++ b/app/library/EventsSubscriber.py
@@ -41,6 +41,8 @@ class Events:
TASK_FINISHED = "task_finished"
TASK_ERROR = "task_error"
+ PRESETS_ADD = "preset_add"
+
@dataclass(kw_only=True)
class Event:
diff --git a/app/library/HttpAPI.py b/app/library/HttpAPI.py
index 7369cf46..2479085e 100644
--- a/app/library/HttpAPI.py
+++ b/app/library/HttpAPI.py
@@ -29,6 +29,7 @@ from .ffprobe import ffprobe
from .M3u8 import M3u8
from .Notifications import Notification, NotificationEvents
from .Playlist import Playlist
+from .Presets import Presets
from .Segments import Segments
from .Subtitle import Subtitle
from .Tasks import Task, Tasks
@@ -578,6 +579,22 @@ class HttpAPI(Common):
dumps=self.encoder.encode,
)
+ @route("GET", "api/presets")
+ async def presets(self, _: Request) -> Response:
+ """
+ Get the presets.
+
+ Args:
+ _: The request object.
+
+ Returns:
+ Response: The response object.
+
+ """
+ return web.json_response(
+ data=Presets.get_instance().get_all(), status=web.HTTPOk.status_code, dumps=self.encoder.encode
+ )
+
@route("GET", "api/tasks")
async def tasks(self, _: Request) -> Response:
"""
diff --git a/app/library/Presets.py b/app/library/Presets.py
new file mode 100644
index 00000000..3e850b6c
--- /dev/null
+++ b/app/library/Presets.py
@@ -0,0 +1,234 @@
+import asyncio
+import json
+import logging
+import os
+from dataclasses import dataclass, field
+from typing import Any
+
+from aiohttp import web
+
+from .config import Config
+from .Emitter import Emitter
+from .encoder import Encoder
+from .EventsSubscriber import Event, Events, EventsSubscriber
+from .Singleton import Singleton
+
+LOG = logging.getLogger("presets")
+
+
+@dataclass(kw_only=True)
+class Preset:
+ name: str
+ """The name of the preset."""
+
+ format: str
+ """The format of the preset."""
+
+ args: dict[str, list[str] | bool] | None = field(default_factory=dict)
+ """The arguments of the preset."""
+
+ postprocessors: list | None = field(default_factory=list)
+ """The postprocessors of the preset."""
+
+ def serialize(self) -> dict:
+ return self.__dict__
+
+ def json(self) -> str:
+ return Encoder().encode(self.serialize())
+
+ def get(self, key: str, default: Any = None) -> Any:
+ return self.serialize().get(key, default)
+
+
+class Presets(metaclass=Singleton):
+ """
+ This class is used to manage the presets.
+ """
+
+ _presets: list[Preset] = []
+ """The list of presets."""
+
+ _instance = None
+ """The instance of the class."""
+
+ def __init__(
+ self,
+ file: str | None = None,
+ emitter: Emitter | None = None,
+ loop: asyncio.AbstractEventLoop | None = None,
+ config: Config | None = None,
+ ):
+ Presets._instance = self
+
+ config = config or Config.get_instance()
+
+ self._file: str = file or os.path.join(config.config_path, "presets.json")
+ self._loop: asyncio.AbstractEventLoop = loop or asyncio.get_event_loop()
+ self._emitter: Emitter = emitter or Emitter.get_instance()
+
+ if os.path.exists(self._file) and "600" != oct(os.stat(self._file).st_mode)[-3:]:
+ try:
+ os.chmod(self._file, 0o600)
+ except Exception:
+ pass
+
+ def handle_event(_, e: Event):
+ self.save(**e.data)
+
+ EventsSubscriber.get_instance().subscribe(Events.PRESETS_ADD, f"{__class__}.save", handle_event)
+
+ @staticmethod
+ def get_instance() -> "Presets":
+ """
+ Get the instance of the class.
+
+ Returns:
+ Presets: The instance of the class
+
+ """
+ if not Presets._instance:
+ Presets._instance = Presets()
+
+ return Presets._instance
+
+ async def on_shutdown(self, _: web.Application):
+ pass
+
+ def attach(self, _: web.Application):
+ """
+ Attach the work to the aiohttp application.
+
+ Args:
+ _ (web.Application): The aiohttp application.
+
+ Returns:
+ None
+
+ """
+ self.load()
+
+ def get_all(self) -> list[Preset]:
+ """Return the presets."""
+ return self._presets
+
+ def load(self) -> "Presets":
+ """
+ Load the Presets.
+
+ Returns:
+ Presets: The current instance.
+
+ """
+ self.clear()
+
+ if not os.path.exists(self._file) or os.path.getsize(self._file) < 10:
+ return self
+
+ LOG.info(f"Loading presets from '{self._file}'.")
+ try:
+ with open(self._file) as f:
+ presets = json.load(f)
+ except Exception as e:
+ LOG.error(f"Failed to parse presets from '{self._file}'. '{e}'.")
+ return self
+
+ if not presets or len(presets) < 1:
+ LOG.info(f"No presets were defined in '{self._file}'.")
+ return self
+
+ for i, preset in enumerate(presets):
+ try:
+ preset = Preset(**preset)
+ self._presets.append(preset)
+ except Exception as e:
+ LOG.error(f"Failed to parse preset at list position '{i}'. '{e!s}'.")
+ continue
+
+ return self
+
+ def clear(self) -> "Presets":
+ """
+ Clear all presets
+
+ Returns:
+ Presets: The current instance.
+
+ """
+ if len(self._presets) < 1:
+ return self
+
+ self._presets.clear()
+
+ return self
+
+ def validate(self, preset: Preset | dict) -> bool:
+ """
+ Validate the preset.
+
+ Args:
+ preset (Preset|dict): The preset to validate.
+
+ Returns:
+ bool: True if the preset is valid, False otherwise.
+
+ """
+ if not isinstance(preset, dict):
+ if not isinstance(preset, Preset):
+ msg = "Invalid preset type."
+ raise ValueError(msg) # noqa: TRY004
+
+ preset = preset.serialize()
+
+ if not preset.get("name"):
+ msg = "No name found."
+ raise ValueError(msg)
+
+ if not preset.get("format"):
+ msg = "No format found."
+ raise ValueError(msg)
+
+ if preset.get("args") and not isinstance(preset.get("args"), dict):
+ msg = "Invalid args type. expected dict."
+ raise ValueError(msg)
+
+ if preset.get("postprocessors") and not isinstance(preset.get("postprocessors"), list):
+ msg = "Invalid postprocessors type. expected list."
+ raise ValueError(msg)
+
+ return True
+
+ def save(self, presets: list[Preset | dict]) -> "Presets":
+ """
+ Save the presets.
+
+ Args:
+ presets (list[Preset]): The presets to save.
+
+ Returns:
+ Presets: The current instance.
+
+ """
+ for i, preset in enumerate(presets):
+ try:
+ if not isinstance(preset, Preset):
+ preset = Preset(**preset)
+ presets[i] = preset
+ except Exception as e:
+ LOG.error(f"Failed to save preset '{i}' due to parsing error. '{e!s}'.")
+ continue
+
+ try:
+ self.validate(preset)
+ except ValueError as e:
+ LOG.error(f"Failed to validate preset '{i}: {preset.name}'. '{e}'.")
+ continue
+
+ try:
+ with open(self._file, "w") as f:
+ json.dump(obj=[preset.serialize() for preset in presets], fp=f, indent=4)
+
+ LOG.info(f"Presets saved to '{self._file}'.")
+ except Exception as e:
+ LOG.error(f"Failed to save presets to '{self._file}'. '{e!s}'.")
+
+ return self
diff --git a/app/main.py b/app/main.py
index ee857722..10c4b658 100644
--- a/app/main.py
+++ b/app/main.py
@@ -17,6 +17,7 @@ from library.HttpAPI import HttpAPI
from library.HttpSocket import HttpSocket
from library.Notifications import Notification
from library.PackageInstaller import PackageInstaller
+from library.Presets import Presets
from library.Tasks import Tasks
LOG = logging.getLogger("app")
@@ -96,6 +97,7 @@ class Main:
self._http.attach(self._app)
self._queue.attach(self._app)
Tasks.get_instance().attach(self._app)
+ Presets.get_instance().attach(self._app)
def started(_):
LOG.info("=" * 40)
From b7b72cf21e19c84faecea28b32c58a186f7866d4 Mon Sep 17 00:00:00 2001
From: ArabCoders
Date: Thu, 27 Feb 2025 18:31:17 +0300
Subject: [PATCH 04/10] try to direct play video first and fallback to hls if
we encounter error.
---
.vscode/launch.json | 3 +-
app/library/HttpAPI.py | 41 ++++++++++
app/library/Playlist.py | 41 ++--------
app/library/Utils.py | 27 +++++++
app/library/encoder.py | 13 +++-
ui/components/History.vue | 39 ++--------
ui/components/VideoPlayer.vue | 138 ++++++++++++++++++++++------------
ui/utils/index.js | 5 +-
8 files changed, 186 insertions(+), 121 deletions(-)
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 96b9c850..da500c43 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -21,7 +21,8 @@
"NUXT_API_URL": "http://localhost:8081/api/",
"NUXT_PUBLIC_WSS": ":8081/",
},
- "console": "internalConsole"
+ "console": "internalConsole",
+ "outputCapture": "std",
},
{
"name": "Python: main.py",
diff --git a/app/library/HttpAPI.py b/app/library/HttpAPI.py
index 2479085e..4ffef7b1 100644
--- a/app/library/HttpAPI.py
+++ b/app/library/HttpAPI.py
@@ -38,6 +38,7 @@ from .Utils import (
StreamingError,
arg_converter,
calc_download_path,
+ get_sidecar_subtitles,
get_video_info,
validate_url,
validate_uuid,
@@ -1178,6 +1179,46 @@ class HttpAPI(Common):
except Exception as e:
return web.json_response(data={"error": str(e)}, status=web.HTTPInternalServerError.status_code)
+ @route("GET", "api/file/info/{file:.*}")
+ async def get_file_info(self, request: Request) -> Response:
+ """
+ Get file info
+
+ Args:
+ request (Request): The request object.
+
+ Returns:
+ Response: The response object.
+
+ """
+ file: str = request.match_info.get("file")
+ if not file:
+ return web.json_response(data={"error": "file is required."}, status=web.HTTPBadRequest.status_code)
+
+ try:
+ realFile: str = calc_download_path(base_path=self.config.download_path, folder=file, create_path=False)
+ if not os.path.exists(realFile) or not os.path.isfile(realFile):
+ return web.json_response(
+ data={"error": f"File '{file}' does not exist."}, status=web.HTTPNotFound.status_code
+ )
+
+ realFile = Path(realFile)
+
+ response = {
+ "ffprobe": await ffprobe(realFile),
+ "sidecar": get_sidecar_subtitles(realFile),
+ }
+
+ for i, f in enumerate(response["sidecar"]):
+ response["sidecar"][i]["file"] = str(Path(realFile).with_name(f["file"].name)).replace(
+ self.config.download_path, ""
+ ).strip("/")
+
+ return web.json_response(data=response, status=web.HTTPOk.status_code, dumps=self.encoder.encode)
+ except Exception as e:
+ LOG.exception(e)
+ return web.json_response(data={"error": str(e)}, status=web.HTTPInternalServerError.status_code)
+
@route("GET", "api/youtube/auth")
async def is_authenticated(self, request: Request) -> Response:
"""
diff --git a/app/library/Playlist.py b/app/library/Playlist.py
index a83074ca..befd9193 100644
--- a/app/library/Playlist.py
+++ b/app/library/Playlist.py
@@ -1,13 +1,10 @@
-import glob
-import re
from pathlib import Path
from urllib.parse import quote
from aiohttp.web import HTTPFound, Response
from .ffprobe import ffprobe
-from .Subtitle import Subtitle
-from .Utils import StreamingError, calc_download_path, check_id
+from .Utils import StreamingError, calc_download_path, check_id, get_sidecar_subtitles
class Playlist:
@@ -41,28 +38,19 @@ class Playlist:
msg = f"Unable to get '{rFile}' duration."
raise StreamingError(msg)
- duration: float = float(ff.metadata.get("duration"))
-
playlist = []
playlist.append("#EXTM3U")
subs = ""
- index = 0
- for item in self.get_sidecar_files(rFile):
- if item.suffix not in Subtitle.allowed_extensions:
- continue
-
- index += 1
- lang: str = "und"
- lg = re.search(r"\.(?P\w{2,3})\.\w{3}$", item.name)
- if lg:
- lang = lg.groupdict().get("lang")
+ duration: float = float(ff.metadata.get("duration"))
+ for sub_file in get_sidecar_subtitles(rFile):
+ lang = sub_file["lang"]
+ item = sub_file["file"]
+ name = sub_file["name"]
subs = ',SUBTITLES="subs"'
-
url = f"{self.url}api/player/m3u8/subtitle/{quote(str(Path(file).with_name(item.name)))}.m3u8?duration={duration}"
- name = f"{item.suffix[1:].upper()} ({index}) - {lang}"
playlist.append(
f'#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="{name}",DEFAULT=NO,AUTOSELECT=NO,FORCED=NO,LANGUAGE="{lang}",URI="{url}"'
)
@@ -71,20 +59,3 @@ class Playlist:
playlist.append(f"{self.url}api/player/m3u8/video/{quote(file)}.m3u8")
return "\n".join(playlist)
-
- def get_sidecar_files(self, file: Path) -> list[Path]:
- """
- Get sidecar files for the given file.
-
- :param file: File to get sidecar files for.
- :return: List of sidecar files.
- """
- files = []
-
- for sub_file in file.parent.glob(f"{glob.escape(file.stem)}.*"):
- if sub_file == file or sub_file.is_file() is False or sub_file.stem.startswith("."):
- continue
-
- files.append(sub_file)
-
- return files
diff --git a/app/library/Utils.py b/app/library/Utils.py
index b8e3fe7d..bad19221 100644
--- a/app/library/Utils.py
+++ b/app/library/Utils.py
@@ -1,4 +1,5 @@
import copy
+import glob
import ipaddress
import json
import logging
@@ -27,6 +28,8 @@ IGNORED_KEYS: tuple[str] = (
)
YTDLP_INFO_CLS: yt_dlp.YoutubeDL = None
+ALLOWED_SUBS_EXTENSIONS: tuple[str] = (".srt", ".vtt", ".ass")
+
class StreamingError(Exception):
"""Raised when an error occurs during streaming."""
@@ -524,3 +527,27 @@ def validate_uuid(uuid_str: str, version: int = 4) -> bool:
return True
except ValueError:
return False
+
+
+def get_sidecar_subtitles(file: pathlib.Path) -> list[dict]:
+ """
+ Get sidecar files for the given file.
+
+ :param file: File to get sidecar files for.
+ :return: List of sidecar files.
+ """
+ files = []
+
+ for i, f in enumerate(file.parent.glob(f"{glob.escape(file.stem)}.*")):
+ if f == file or f.is_file() is False or f.stem.startswith("."):
+ continue
+
+ if f.suffix not in ALLOWED_SUBS_EXTENSIONS:
+ continue
+
+ lg = re.search(r"\.(?P\w{2,3})\.\w{3}$", f.name)
+ lang = lg.groupdict().get("lang") if lg else "und"
+
+ files.append({"file": f, "lang": lang, "name": f"{f.suffix[1:].upper()} ({i}) - {lang}"})
+
+ return files
diff --git a/app/library/encoder.py b/app/library/encoder.py
index 2a788649..0ed61c57 100644
--- a/app/library/encoder.py
+++ b/app/library/encoder.py
@@ -1,4 +1,5 @@
import json
+from pathlib import Path
class Encoder(json.JSONEncoder):
@@ -9,10 +10,14 @@ class Encoder(json.JSONEncoder):
"""
def default(self, o):
- if isinstance(o, object) and hasattr(o, "serialize"):
- return o.serialize()
+ if isinstance(o, Path):
+ return str(o)
- if isinstance(o, object) and hasattr(o, "__dict__"):
- return o.__dict__
+ if isinstance(o, object):
+ if hasattr(o, "serialize"):
+ return o.serialize()
+
+ if hasattr(o, "__dict__"):
+ return o.__dict__
return json.JSONEncoder.default(self, o)
diff --git a/ui/components/History.vue b/ui/components/History.vue
index b5aab95d..44be0a0f 100644
--- a/ui/components/History.vue
+++ b/ui/components/History.vue
@@ -235,12 +235,11 @@
-
+
@@ -264,36 +263,10 @@ const showCompleted = useStorage('showCompleted', true)
const hideThumbnail = useStorage('hideThumbnailHistory', false)
const direction = useStorage('sortCompleted', 'desc')
-const video_link = ref('')
-const video_title = ref('')
-const video_thumbnail = ref('')
-const video_artist = ref('')
+const video_item = ref(null)
-const playVideo = item => {
- video_thumbnail.value = '';
- video_artist.value = '';
- video_link.value = makeDownload(config, item, 'm3u8')
- video_title.value = item.title
- if (item.extras?.thumbnail) {
- video_thumbnail.value = '/api/thumbnail?url=' + encodePath(item.extras.thumbnail)
- }
- if (item.extras?.channel) {
- video_artist.value = item.extras.channel
- }
- if (!video_artist.value && item.extras?.uploader) {
- video_artist.value = item.extras.uploader
- }
- if (!item.extras?.is_video && item.extras?.is_audio) {
- video_audio.value = true
- }
-}
-
-const closeVideo = () => {
- video_link.value = ''
- video_title.value = ''
- video_thumbnail.value = ''
- video_artist.value = ''
-}
+const playVideo = item => video_item.value = item
+const closeVideo = () => video_item.value = null
watch(masterSelectAll, (value) => {
for (const key in stateStore.history) {
diff --git a/ui/components/VideoPlayer.vue b/ui/components/VideoPlayer.vue
index e1b32a44..e27df2f5 100644
--- a/ui/components/VideoPlayer.vue
+++ b/ui/components/VideoPlayer.vue
@@ -18,8 +18,10 @@
-
@@ -29,33 +31,27 @@ import { onMounted, onUpdated, ref, defineProps, defineEmits, onUnmounted } from
import Hls from 'hls.js'
import Plyr from 'plyr'
import 'plyr/dist/plyr.css'
+import { makeDownload } from '~/utils/index'
+const config = useConfigStore()
const props = defineProps({
- link: {
- type: String,
- default: ''
- },
- title: {
- type: String,
- default: ''
- },
- thumbnail: {
- type: String,
- default: ''
- },
- artist: {
- type: String,
- default: ''
- },
- isControls: {
- type: Boolean,
- default: true
+ item: {
+ type: Object,
+ default: () => ({})
},
})
const emitter = defineEmits(['closeModel'])
const video = ref(null)
+const tracks = ref([])
+const sources = ref([])
+
+const thumbnail = ref('')
+const artist = ref('')
+const title = ref('')
+const isAudio = ref(false)
+
let player = null;
let hls = null;
@@ -65,7 +61,43 @@ const eventFunc = e => {
}
}
-onMounted(() => {
+onMounted(async () => {
+ const response = await (await request(makeDownload(config, props.item, 'api/file/info'))).json()
+
+ if (props.item.extras?.thumbnail) {
+ thumbnail.value = '/api/thumbnail?url=' + encodePath(props.item.extras.thumbnail)
+ }
+
+ sources.value.push({
+ src: makeDownload(config, props.item, 'api/download'),
+ onerror: e => src_error(e),
+ })
+
+ if (props.item.extras?.channel) {
+ artist.value = props.item.extras.channel
+ }
+
+ if (!artist.value && props.item.extras?.uploader) {
+ artist.value = props.item.extras.uploader
+ }
+
+ if (props.item?.title) {
+ title.value = props.item.title
+ }
+
+ if (!props.item.extras?.is_video && props.item.extras?.is_audio) {
+ isAudio.value = true
+ }
+
+ response.sidecar.forEach((cap, id) => {
+ tracks.value.push({
+ kind: "captions",
+ label: cap.name,
+ lang: cap.lang,
+ file: `${makeDownload(config, { filename: cap.file }, 'api/player/subtitle')}.vtt`
+ })
+ })
+
if (/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent)) {
document.documentElement.style.setProperty('--webkit-text-track-display', 'block');
}
@@ -86,23 +118,23 @@ onUnmounted(() => {
window.removeEventListener('keydown', eventFunc)
- if (props.title) {
+ if (title.value) {
window.document.title = 'YTPTube'
}
})
const prepareVideoPlayer = () => {
let mediaMetadata = {
- title: props.title,
+ title: title.value,
};
- if (props.thumbnail) {
+ if (thumbnail.value) {
mediaMetadata['artwork'] = [
- { src: props.thumbnail, sizes: '1920x1080', type: 'image/jpeg' },
+ { src: thumbnail.value, sizes: '1920x1080', type: 'image/jpeg' },
]
}
- if (props.artist) {
- mediaMetadata['artist'] = props.artist
+ if (artist.value) {
+ mediaMetadata['artist'] = artist.value
}
let opts = {
@@ -121,28 +153,47 @@ const prepareVideoPlayer = () => {
enabled: true,
key: 'plyr'
},
- poster: props.thumbnail,
- artist: props.artist,
- title: props.title,
+ artist: artist.value,
mediaMetadata: mediaMetadata,
captions: {
update: true,
- }
+ },
};
- if (props.artist) {
- opts.artist = props.artist
+ if (artist.value) {
+ opts.artist = artist.value
}
- if (props.title) {
- opts.title = props.title
+ if (title.value) {
+ opts.title = title.value
}
- if (props.thumbnail) {
- opts.poster = props.thumbnail
+ if (thumbnail.value) {
+ opts.poster = thumbnail.value
}
+
player = new Plyr(video.value, opts);
+ player.source = {
+ type: isAudio.value ? 'audio' : 'video',
+ title: title.value,
+ poster: thumbnail.value,
+ };
+
+ if (title.value) {
+ window.document.title = `YTPTube - Playing: ${title.value}`
+ }
+}
+
+const src_error = () => {
+ if (hls) {
+ return
+ }
+ console.warn('Direct play failed, trying HLS.');
+ attach_hls(makeDownload(config, props.item, 'm3u8'));
+}
+
+const attach_hls = link => {
hls = new Hls({
debug: false,
enableWorker: true,
@@ -151,14 +202,7 @@ const prepareVideoPlayer = () => {
fragLoadingTimeOut: 200000,
});
- hls.loadSource(props.link)
-
- if (video.value) {
- hls.attachMedia(video.value)
- }
-
- if (props.title) {
- window.document.title = `YTPTube - Playing: ${props.title}`
- }
+ hls.loadSource(link)
+ hls.attachMedia(video.value)
}
diff --git a/ui/utils/index.js b/ui/utils/index.js
index 47960e61..292eabff 100644
--- a/ui/utils/index.js
+++ b/ui/utils/index.js
@@ -350,7 +350,10 @@ const getQueryParams = (url = window.location.search) => Object.fromEntries(new
* @returns {string} The download URL
*/
const makeDownload = (config, item, base = 'api/download') => {
- let baseDir = 'api/download' === base ? `${base}/` : 'api/player/playlist/';
+ let baseDir = 'api/player/m3u8/video/';
+ if ('m3u8' !== base) {
+ baseDir = `${base}/`;
+ }
if (item.folder) {
item.folder = item.folder.replace(/#/g, '%23');
From 63a9a15e67e6b956b78b7c9369e505fe454970f4 Mon Sep 17 00:00:00 2001
From: ArabCoders
Date: Thu, 27 Feb 2025 18:42:35 +0300
Subject: [PATCH 05/10] do not consider 0 byte files.
---
app/library/Utils.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/app/library/Utils.py b/app/library/Utils.py
index bad19221..45c26df1 100644
--- a/app/library/Utils.py
+++ b/app/library/Utils.py
@@ -545,6 +545,9 @@ def get_sidecar_subtitles(file: pathlib.Path) -> list[dict]:
if f.suffix not in ALLOWED_SUBS_EXTENSIONS:
continue
+ if f.stat().st_size < 1:
+ continue
+
lg = re.search(r"\.(?P\w{2,3})\.\w{3}$", f.name)
lang = lg.groupdict().get("lang") if lg else "und"
From 3a964a6ac3a78e8f4091effc88bd531de24badc2 Mon Sep 17 00:00:00 2001
From: ArabCoders
Date: Thu, 27 Feb 2025 19:19:32 +0300
Subject: [PATCH 06/10] add mimetype to source list
---
.vscode/settings.json | 3 +++
app/library/HttpAPI.py | 12 ++++++---
app/library/Utils.py | 50 +++++++++++++++++++++++++++++++++++
ui/components/VideoPlayer.vue | 4 ++-
4 files changed, 64 insertions(+), 5 deletions(-)
diff --git a/.vscode/settings.json b/.vscode/settings.json
index f21e8522..ac6857c9 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -23,13 +23,16 @@
"httpx",
"libcurl",
"libx",
+ "matroska",
"mpegts",
+ "msvideo",
"muxdelay",
"nodesc",
"noprogress",
"postprocessor",
"preferredcodec",
"preferredquality",
+ "quicktime",
"tmpfilename",
"vcodec",
"vconvert",
diff --git a/app/library/HttpAPI.py b/app/library/HttpAPI.py
index 4ffef7b1..c8ac7162 100644
--- a/app/library/HttpAPI.py
+++ b/app/library/HttpAPI.py
@@ -38,6 +38,7 @@ from .Utils import (
StreamingError,
arg_converter,
calc_download_path,
+ get_mime_type,
get_sidecar_subtitles,
get_video_info,
validate_url,
@@ -1204,15 +1205,18 @@ class HttpAPI(Common):
realFile = Path(realFile)
+ ff_info = await ffprobe(realFile)
+
response = {
- "ffprobe": await ffprobe(realFile),
+ "ffprobe": ff_info,
+ "mimetype": get_mime_type(ff_info.get("metadata", {}), realFile),
"sidecar": get_sidecar_subtitles(realFile),
}
for i, f in enumerate(response["sidecar"]):
- response["sidecar"][i]["file"] = str(Path(realFile).with_name(f["file"].name)).replace(
- self.config.download_path, ""
- ).strip("/")
+ response["sidecar"][i]["file"] = (
+ str(Path(realFile).with_name(f["file"].name)).replace(self.config.download_path, "").strip("/")
+ )
return web.json_response(data=response, status=web.HTTPOk.status_code, dumps=self.encoder.encode)
except Exception as e:
diff --git a/app/library/Utils.py b/app/library/Utils.py
index 45c26df1..7a986130 100644
--- a/app/library/Utils.py
+++ b/app/library/Utils.py
@@ -554,3 +554,53 @@ def get_sidecar_subtitles(file: pathlib.Path) -> list[dict]:
files.append({"file": f, "lang": lang, "name": f"{f.suffix[1:].upper()} ({i}) - {lang}"})
return files
+
+
+def get_mime_type(metadata: dict, file_path: pathlib.Path) -> str:
+ """
+ Determine the correct MIME type for a video file based on ffprobe metadata.
+
+ Args:
+ metadata (dict): Parsed JSON output from ffprobe.
+ file_path (str): The path to the video file for fallback detection.
+
+ Returns:
+ str: MIME type compatible with HTML5 tag.
+
+ """
+ # Extract format name from ffprobe
+ format_name = metadata.get("format_name", "")
+
+ # Define mappings for HTML5-compatible video types
+ format_to_mime = {
+ "matroska": "video/x-matroska", # Default for MKV
+ "webm": "video/webm", # MKV can also be WebM
+ "mp4": "video/mp4",
+ "mov": "video/quicktime",
+ "avi": "video/x-msvideo",
+ "flv": "video/x-flv",
+ "ogg": "video/ogg",
+ "mpegts": "video/mp2t",
+ "3gp": "video/3gpp",
+ }
+
+ # Check format_name against known formats
+ if format_name:
+ selected = None
+ for fmt in format_name.split(","):
+ fmt = fmt.strip().lower()
+ if fmt in format_to_mime:
+ selected = format_to_mime[fmt]
+
+ if selected:
+ return selected
+
+ # Fallback: Use Python's mimetypes module
+ import mimetypes
+
+ mime_type, _ = mimetypes.guess_type(str(file_path))
+ if mime_type:
+ return mime_type
+
+ # Final fallback: Return generic binary type
+ return "application/octet-stream"
diff --git a/ui/components/VideoPlayer.vue b/ui/components/VideoPlayer.vue
index e27df2f5..c1244291 100644
--- a/ui/components/VideoPlayer.vue
+++ b/ui/components/VideoPlayer.vue
@@ -19,7 +19,8 @@
-
+
@@ -70,6 +71,7 @@ onMounted(async () => {
sources.value.push({
src: makeDownload(config, props.item, 'api/download'),
+ type: response.mimetype,
onerror: e => src_error(e),
})
From 689ce421e910a2d7f31ff3c639e2e8abf3e6e95b Mon Sep 17 00:00:00 2001
From: ArabCoders
Date: Thu, 27 Feb 2025 23:54:49 +0300
Subject: [PATCH 07/10] add sentry for webui error reporting
---
app/library/config.py | 4 +
ui/layouts/default.vue | 3 +
ui/nuxt.config.ts | 2 +
ui/package.json | 1 +
ui/stores/ConfigStore.js | 1 +
ui/yarn.lock | 918 ++++++++++++++++++++++++++++++++++++++-
6 files changed, 919 insertions(+), 10 deletions(-)
diff --git a/app/library/config.py b/app/library/config.py
index 3b768ef5..68b0826b 100644
--- a/app/library/config.py
+++ b/app/library/config.py
@@ -143,6 +143,9 @@ class Config:
file_logging: bool = False
"Enable file logging."
+ sentry_dsn: str | None = None
+ "The Sentry DSN to use for error reporting."
+
_manual_vars: tuple = (
"temp_path",
"config_path",
@@ -200,6 +203,7 @@ class Config:
"basic_mode",
"default_preset",
"instance_title",
+ "sentry_dsn",
)
"The variables that are relevant to the frontend."
diff --git a/ui/layouts/default.vue b/ui/layouts/default.vue
index b2c3edb3..28eec019 100644
--- a/ui/layouts/default.vue
+++ b/ui/layouts/default.vue
@@ -93,6 +93,7 @@ import 'assets/css/style.css'
import 'assets/css/all.css'
import { useStorage } from '@vueuse/core'
import moment from 'moment'
+import * as Sentry from "@sentry/nuxt";
const Year = new Date().getFullYear()
const selectedTheme = useStorage('theme', 'auto')
@@ -144,6 +145,8 @@ const applyPreferredColorScheme = scheme => {
}
}
+watch(() => config.app.sentry_dsn, dsn => dsn ? Sentry.init({ dsn: dsn }) : null)
+
onMounted(async () => {
try {
applyPreferredColorScheme(selectedTheme.value)
diff --git a/ui/nuxt.config.ts b/ui/nuxt.config.ts
index 7cfe514a..dfa430d3 100644
--- a/ui/nuxt.config.ts
+++ b/ui/nuxt.config.ts
@@ -33,6 +33,7 @@ export default defineNuxtConfig({
domain: '/',
wss: process.env.VUE_APP_BASE_URL ?? '',
version: '2.0.0',
+ sentry: process.env.NUXT_PUBLIC_SENTRY_DSN ?? '',
}
},
build: {
@@ -60,6 +61,7 @@ export default defineNuxtConfig({
'@pinia/nuxt',
'@vueuse/nuxt',
'floating-vue/nuxt',
+ '@sentry/nuxt/module',
],
nitro: {
diff --git a/ui/package.json b/ui/package.json
index 141eb393..fb351aa1 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -12,6 +12,7 @@
"web-types": "./web-types.json",
"dependencies": {
"@pinia/nuxt": "^0.5.1",
+ "@sentry/nuxt": "^9.2.0",
"@vueuse/core": "^10.9.0",
"@vueuse/nuxt": "^10.9.0",
"@xterm/addon-fit": "^0.10.0",
diff --git a/ui/stores/ConfigStore.js b/ui/stores/ConfigStore.js
index a9497709..2fde0e1d 100644
--- a/ui/stores/ConfigStore.js
+++ b/ui/stores/ConfigStore.js
@@ -15,6 +15,7 @@ const CONFIG_KEYS = {
basic_mode: true,
default_preset: 'default',
instance_title: null,
+ sentry_dsn: null,
},
presets: [
{
diff --git a/ui/yarn.lock b/ui/yarn.lock
index bc007670..8590f690 100644
--- a/ui/yarn.lock
+++ b/ui/yarn.lock
@@ -29,7 +29,7 @@
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367"
integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==
-"@babel/core@^7.23.0", "@babel/core@^7.26.0":
+"@babel/core@^7.18.5", "@babel/core@^7.23.0", "@babel/core@^7.26.0":
version "7.26.9"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.9.tgz#71838542a4b1e49dfed353d7acbc6eb89f4a76f2"
integrity sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==
@@ -593,7 +593,7 @@
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.25"
-"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0":
+"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15", "@jridgewell/sourcemap-codec@^1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
@@ -774,7 +774,7 @@
which "^3.0.1"
ws "^8.18.0"
-"@nuxt/kit@3.15.4", "@nuxt/kit@^3.12.1", "@nuxt/kit@^3.15.0", "@nuxt/kit@^3.15.4", "@nuxt/kit@^3.9.0":
+"@nuxt/kit@3.15.4", "@nuxt/kit@^3.12.1", "@nuxt/kit@^3.13.2", "@nuxt/kit@^3.15.0", "@nuxt/kit@^3.15.4", "@nuxt/kit@^3.9.0":
version "3.15.4"
resolved "https://registry.yarnpkg.com/@nuxt/kit/-/kit-3.15.4.tgz#122f511e518573320a035b5e24adf0118d51485d"
integrity sha512-dr7I7eZOoRLl4uxdxeL2dQsH0OrbEiVPIyBHnBpA4co24CBnoJoF+JINuP9l3PAM3IhUzc5JIVq3/YY3lEc3Hw==
@@ -866,6 +866,319 @@
vite-plugin-checker "^0.8.0"
vue-bundle-renderer "^2.1.1"
+"@opentelemetry/api-logs@0.56.0":
+ version "0.56.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.56.0.tgz#68f8c51ca905c260b610c8a3c67d3f9fa3d59a45"
+ integrity sha512-Wr39+94UNNG3Ei9nv3pHd4AJ63gq5nSemMRpCd8fPwDL9rN3vK26lzxfH27mw16XzOSO+TpyQwBAMaLxaPWG0g==
+ dependencies:
+ "@opentelemetry/api" "^1.3.0"
+
+"@opentelemetry/api-logs@0.57.1":
+ version "0.57.1"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.57.1.tgz#97ebd714f0b1fcdf896e85c465ae5c5b22747425"
+ integrity sha512-I4PHczeujhQAQv6ZBzqHYEUiggZL4IdSMixtVD3EYqbdrjujE7kRfI5QohjlPoJm8BvenoW5YaTMWRrbpot6tg==
+ dependencies:
+ "@opentelemetry/api" "^1.3.0"
+
+"@opentelemetry/api-logs@0.57.2":
+ version "0.57.2"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.57.2.tgz#d4001b9aa3580367b40fe889f3540014f766cc87"
+ integrity sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==
+ dependencies:
+ "@opentelemetry/api" "^1.3.0"
+
+"@opentelemetry/api@^1.3.0", "@opentelemetry/api@^1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe"
+ integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==
+
+"@opentelemetry/context-async-hooks@^1.30.1":
+ version "1.30.1"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.1.tgz#4f76280691a742597fd0bf682982126857622948"
+ integrity sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA==
+
+"@opentelemetry/core@1.30.1", "@opentelemetry/core@^1.1.0", "@opentelemetry/core@^1.26.0", "@opentelemetry/core@^1.30.1", "@opentelemetry/core@^1.8.0":
+ version "1.30.1"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.30.1.tgz#a0b468bb396358df801881709ea38299fc30ab27"
+ integrity sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==
+ dependencies:
+ "@opentelemetry/semantic-conventions" "1.28.0"
+
+"@opentelemetry/instrumentation-amqplib@^0.46.0":
+ version "0.46.1"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.46.1.tgz#7101678488d0e942162ca85c9ac6e93e1f3e0008"
+ integrity sha512-AyXVnlCf/xV3K/rNumzKxZqsULyITJH6OVLiW6730JPRqWA7Zc9bvYoVNpN6iOpTU8CasH34SU/ksVJmObFibQ==
+ dependencies:
+ "@opentelemetry/core" "^1.8.0"
+ "@opentelemetry/instrumentation" "^0.57.1"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+
+"@opentelemetry/instrumentation-connect@0.43.0":
+ version "0.43.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.43.0.tgz#411035f4a8f2e498dbfa7300e545c58586a062e2"
+ integrity sha512-Q57JGpH6T4dkYHo9tKXONgLtxzsh1ZEW5M9A/OwKrZFyEpLqWgjhcZ3hIuVvDlhb426iDF1f9FPToV/mi5rpeA==
+ dependencies:
+ "@opentelemetry/core" "^1.8.0"
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+ "@types/connect" "3.4.36"
+
+"@opentelemetry/instrumentation-dataloader@0.16.0":
+ version "0.16.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.16.0.tgz#913345c335f67bf8e17a9b38c227dba741fe488b"
+ integrity sha512-88+qCHZC02up8PwKHk0UQKLLqGGURzS3hFQBZC7PnGwReuoKjHXS1o29H58S+QkXJpkTr2GACbx8j6mUoGjNPA==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.57.0"
+
+"@opentelemetry/instrumentation-express@0.47.0":
+ version "0.47.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.47.0.tgz#f0477db3b1f4b342beb9ecd08edc26c470566724"
+ integrity sha512-XFWVx6k0XlU8lu6cBlCa29ONtVt6ADEjmxtyAyeF2+rifk8uBJbk1La0yIVfI0DoKURGbaEDTNelaXG9l/lNNQ==
+ dependencies:
+ "@opentelemetry/core" "^1.8.0"
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+
+"@opentelemetry/instrumentation-fastify@0.44.1":
+ version "0.44.1"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.44.1.tgz#c8080f24a6fbdd14689c619ad7b14fe189b10f28"
+ integrity sha512-RoVeMGKcNttNfXMSl6W4fsYoCAYP1vi6ZAWIGhBY+o7R9Y0afA7f9JJL0j8LHbyb0P0QhSYk+6O56OwI2k4iRQ==
+ dependencies:
+ "@opentelemetry/core" "^1.8.0"
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+
+"@opentelemetry/instrumentation-fs@0.19.0":
+ version "0.19.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.19.0.tgz#a44807aea97edc64c597d6a5b5b8637b7ab45057"
+ integrity sha512-JGwmHhBkRT2G/BYNV1aGI+bBjJu4fJUD/5/Jat0EWZa2ftrLV3YE8z84Fiij/wK32oMZ88eS8DI4ecLGZhpqsQ==
+ dependencies:
+ "@opentelemetry/core" "^1.8.0"
+ "@opentelemetry/instrumentation" "^0.57.0"
+
+"@opentelemetry/instrumentation-generic-pool@0.43.0":
+ version "0.43.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.43.0.tgz#b1769eb0e30f2abb764a9cbc811aa3d4560ecc24"
+ integrity sha512-at8GceTtNxD1NfFKGAuwtqM41ot/TpcLh+YsGe4dhf7gvv1HW/ZWdq6nfRtS6UjIvZJOokViqLPJ3GVtZItAnQ==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.57.0"
+
+"@opentelemetry/instrumentation-graphql@0.47.0":
+ version "0.47.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.47.0.tgz#271807e21a6224bd1986a3e9887650f1858ee733"
+ integrity sha512-Cc8SMf+nLqp0fi8oAnooNEfwZWFnzMiBHCGmDFYqmgjPylyLmi83b+NiTns/rKGwlErpW0AGPt0sMpkbNlzn8w==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.57.0"
+
+"@opentelemetry/instrumentation-hapi@0.45.1":
+ version "0.45.1"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.45.1.tgz#5edf982549070d95e20152d568279548ad44d662"
+ integrity sha512-VH6mU3YqAKTePPfUPwfq4/xr049774qWtfTuJqVHoVspCLiT3bW+fCQ1toZxt6cxRPYASoYaBsMA3CWo8B8rcw==
+ dependencies:
+ "@opentelemetry/core" "^1.8.0"
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+
+"@opentelemetry/instrumentation-http@0.57.1":
+ version "0.57.1"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.57.1.tgz#2d8b395df62191475e76fa0eb7bf60079ea886b9"
+ integrity sha512-ThLmzAQDs7b/tdKI3BV2+yawuF09jF111OFsovqT1Qj3D8vjwKBwhi/rDE5xethwn4tSXtZcJ9hBsVAlWFQZ7g==
+ dependencies:
+ "@opentelemetry/core" "1.30.1"
+ "@opentelemetry/instrumentation" "0.57.1"
+ "@opentelemetry/semantic-conventions" "1.28.0"
+ forwarded-parse "2.1.2"
+ semver "^7.5.2"
+
+"@opentelemetry/instrumentation-ioredis@0.47.0":
+ version "0.47.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.47.0.tgz#f83bd133d36d137d2d0b58bfbdfe12ed6fe5ab2f"
+ integrity sha512-4HqP9IBC8e7pW9p90P3q4ox0XlbLGme65YTrA3UTLvqvo4Z6b0puqZQP203YFu8m9rE/luLfaG7/xrwwqMUpJw==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/redis-common" "^0.36.2"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+
+"@opentelemetry/instrumentation-kafkajs@0.7.0":
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.7.0.tgz#079b949ec814b42e49d23bb4d4f73735fe460d52"
+ integrity sha512-LB+3xiNzc034zHfCtgs4ITWhq6Xvdo8bsq7amR058jZlf2aXXDrN9SV4si4z2ya9QX4tz6r4eZJwDkXOp14/AQ==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+
+"@opentelemetry/instrumentation-knex@0.44.0":
+ version "0.44.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.44.0.tgz#af251ed38f06a2f248812c5addf0266697b6149a"
+ integrity sha512-SlT0+bLA0Lg3VthGje+bSZatlGHw/vwgQywx0R/5u9QC59FddTQSPJeWNw29M6f8ScORMeUOOTwihlQAn4GkJQ==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+
+"@opentelemetry/instrumentation-koa@0.47.0":
+ version "0.47.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.47.0.tgz#a74b35809ba95d0f9db49e8c3f214bde475b095a"
+ integrity sha512-HFdvqf2+w8sWOuwtEXayGzdZ2vWpCKEQv5F7+2DSA74Te/Cv4rvb2E5So5/lh+ok4/RAIPuvCbCb/SHQFzMmbw==
+ dependencies:
+ "@opentelemetry/core" "^1.8.0"
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+
+"@opentelemetry/instrumentation-lru-memoizer@0.44.0":
+ version "0.44.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.44.0.tgz#c22e770d950c165f80c657a9c790c9843baaa65b"
+ integrity sha512-Tn7emHAlvYDFik3vGU0mdwvWJDwtITtkJ+5eT2cUquct6nIs+H8M47sqMJkCpyPe5QIBJoTOHxmc6mj9lz6zDw==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.57.0"
+
+"@opentelemetry/instrumentation-mongodb@0.51.0":
+ version "0.51.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.51.0.tgz#8a323c2fb4cb2c93bf95f1b1c0fcb30952d12a08"
+ integrity sha512-cMKASxCX4aFxesoj3WK8uoQ0YUrRvnfxaO72QWI2xLu5ZtgX/QvdGBlU3Ehdond5eb74c2s1cqRQUIptBnKz1g==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+
+"@opentelemetry/instrumentation-mongoose@0.46.0":
+ version "0.46.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.46.0.tgz#c3a5f69e1a5b950b542cf84650fbbd3e31bd681e"
+ integrity sha512-mtVv6UeaaSaWTeZtLo4cx4P5/ING2obSqfWGItIFSunQBrYROfhuVe7wdIrFUs2RH1tn2YYpAJyMaRe/bnTTIQ==
+ dependencies:
+ "@opentelemetry/core" "^1.8.0"
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+
+"@opentelemetry/instrumentation-mysql2@0.45.0":
+ version "0.45.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.45.0.tgz#95501759d470dbc7038670e91205e8ed601ec402"
+ integrity sha512-qLslv/EPuLj0IXFvcE3b0EqhWI8LKmrgRPIa4gUd8DllbBpqJAvLNJSv3cC6vWwovpbSI3bagNO/3Q2SuXv2xA==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+ "@opentelemetry/sql-common" "^0.40.1"
+
+"@opentelemetry/instrumentation-mysql@0.45.0":
+ version "0.45.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.45.0.tgz#e4df8bc709c0c8b0ff90bbef92fb36e92ebe0d19"
+ integrity sha512-tWWyymgwYcTwZ4t8/rLDfPYbOTF3oYB8SxnYMtIQ1zEf5uDm90Ku3i6U/vhaMyfHNlIHvDhvJh+qx5Nc4Z3Acg==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+ "@types/mysql" "2.15.26"
+
+"@opentelemetry/instrumentation-pg@0.51.0":
+ version "0.51.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.51.0.tgz#7d20016a32554ef66c008212dee3ff33fb1a587c"
+ integrity sha512-/NStIcUWUofc11dL7tSgMk25NqvhtbHDCncgm+yc4iJF8Ste2Q/lwUitjfxqj4qWM280uFmBEtcmtMMjbjRU7Q==
+ dependencies:
+ "@opentelemetry/core" "^1.26.0"
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+ "@opentelemetry/sql-common" "^0.40.1"
+ "@types/pg" "8.6.1"
+ "@types/pg-pool" "2.0.6"
+
+"@opentelemetry/instrumentation-redis-4@0.46.0":
+ version "0.46.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.46.0.tgz#828704b8134f023730ac508bcf3a38ca4d5d697c"
+ integrity sha512-aTUWbzbFMFeRODn3720TZO0tsh/49T8H3h8vVnVKJ+yE36AeW38Uj/8zykQ/9nO8Vrtjr5yKuX3uMiG/W8FKNw==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/redis-common" "^0.36.2"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+
+"@opentelemetry/instrumentation-tedious@0.18.0":
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.18.0.tgz#636745423db28e303b4e0289b8f69685cb36f807"
+ integrity sha512-9zhjDpUDOtD+coeADnYEJQ0IeLVCj7w/hqzIutdp5NqS1VqTAanaEfsEcSypyvYv5DX3YOsTUoF+nr2wDXPETA==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.57.0"
+ "@opentelemetry/semantic-conventions" "^1.27.0"
+ "@types/tedious" "^4.0.14"
+
+"@opentelemetry/instrumentation-undici@0.10.0":
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.10.0.tgz#99cba213a6e9d47a82896b6c782c3f2d60e0edb5"
+ integrity sha512-vm+V255NGw9gaSsPD6CP0oGo8L55BffBc8KnxqsMuc6XiAD1L8SFNzsW0RHhxJFqy9CJaJh+YiJ5EHXuZ5rZBw==
+ dependencies:
+ "@opentelemetry/core" "^1.8.0"
+ "@opentelemetry/instrumentation" "^0.57.0"
+
+"@opentelemetry/instrumentation@0.57.1":
+ version "0.57.1"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.57.1.tgz#5aea772be8783a35d69d643da46582f381ba1810"
+ integrity sha512-SgHEKXoVxOjc20ZYusPG3Fh+RLIZTSa4x8QtD3NfgAUDyqdFFS9W1F2ZVbZkqDCdyMcQG02Ok4duUGLHJXHgbA==
+ dependencies:
+ "@opentelemetry/api-logs" "0.57.1"
+ "@types/shimmer" "^1.2.0"
+ import-in-the-middle "^1.8.1"
+ require-in-the-middle "^7.1.1"
+ semver "^7.5.2"
+ shimmer "^1.2.1"
+
+"@opentelemetry/instrumentation@^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || ^0.56.0":
+ version "0.56.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.56.0.tgz#3330ce16d9235a548efa1019a4a7f01414edd44a"
+ integrity sha512-2KkGBKE+FPXU1F0zKww+stnlUxUTlBvLCiWdP63Z9sqXYeNI/ziNzsxAp4LAdUcTQmXjw1IWgvm5CAb/BHy99w==
+ dependencies:
+ "@opentelemetry/api-logs" "0.56.0"
+ "@types/shimmer" "^1.2.0"
+ import-in-the-middle "^1.8.1"
+ require-in-the-middle "^7.1.1"
+ semver "^7.5.2"
+ shimmer "^1.2.1"
+
+"@opentelemetry/instrumentation@^0.57.0", "@opentelemetry/instrumentation@^0.57.1":
+ version "0.57.2"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.57.2.tgz#8924549d7941ba1b5c6f04d5529cf48330456d1d"
+ integrity sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg==
+ dependencies:
+ "@opentelemetry/api-logs" "0.57.2"
+ "@types/shimmer" "^1.2.0"
+ import-in-the-middle "^1.8.1"
+ require-in-the-middle "^7.1.1"
+ semver "^7.5.2"
+ shimmer "^1.2.1"
+
+"@opentelemetry/redis-common@^0.36.2":
+ version "0.36.2"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz#906ac8e4d804d4109f3ebd5c224ac988276fdc47"
+ integrity sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==
+
+"@opentelemetry/resources@1.30.1", "@opentelemetry/resources@^1.30.1":
+ version "1.30.1"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.30.1.tgz#a4eae17ebd96947fdc7a64f931ca4b71e18ce964"
+ integrity sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==
+ dependencies:
+ "@opentelemetry/core" "1.30.1"
+ "@opentelemetry/semantic-conventions" "1.28.0"
+
+"@opentelemetry/sdk-trace-base@^1.30.1":
+ version "1.30.1"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz#41a42234096dc98e8f454d24551fc80b816feb34"
+ integrity sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==
+ dependencies:
+ "@opentelemetry/core" "1.30.1"
+ "@opentelemetry/resources" "1.30.1"
+ "@opentelemetry/semantic-conventions" "1.28.0"
+
+"@opentelemetry/semantic-conventions@1.28.0":
+ version "1.28.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz#337fb2bca0453d0726696e745f50064411f646d6"
+ integrity sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==
+
+"@opentelemetry/semantic-conventions@^1.27.0", "@opentelemetry/semantic-conventions@^1.28.0":
+ version "1.30.0"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.30.0.tgz#3a42c4c475482f2ec87c12aad98832dc0087dc9a"
+ integrity sha512-4VlGgo32k2EQ2wcCY3vEU28A0O13aOtHz3Xt2/2U5FAh9EfhD6t6DqL5Z6yAnRCntbTFDU4YfbpyzSlHNWycPw==
+
+"@opentelemetry/sql-common@^0.40.1":
+ version "0.40.1"
+ resolved "https://registry.yarnpkg.com/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz#93fbc48d8017449f5b3c3274f2268a08af2b83b6"
+ integrity sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==
+ dependencies:
+ "@opentelemetry/core" "^1.1.0"
+
"@parcel/watcher-android-arm64@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz#507f836d7e2042f798c7d07ad19c3546f9848ac1"
@@ -982,6 +1295,13 @@
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.28.tgz#d45e01c4a56f143ee69c54dd6b12eade9e270a73"
integrity sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==
+"@prisma/instrumentation@6.2.1":
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-6.2.1.tgz#261b885467d36759b7ca01d1b2ca4e1120bda886"
+ integrity sha512-QrcWRAwNHXX4nHXB+Q94nfm701gPQsR4zkaxYV6qCiENopRi8yYvXt6FNIvxbuwEiWW5Zid6DoWwIsBKJ/5r5w==
+ dependencies:
+ "@opentelemetry/instrumentation" "^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || ^0.56.0"
+
"@redocly/ajv@^8.11.2":
version "8.11.2"
resolved "https://registry.yarnpkg.com/@redocly/ajv/-/ajv-8.11.2.tgz#46e1bf321ec0ac1e0fd31dea41a3d1fcbdcda0b5"
@@ -1178,6 +1498,283 @@
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz#4cdb2cfae69cdb7b1a3cc58778e820408075e928"
integrity sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==
+"@sentry-internal/browser-utils@9.2.0":
+ version "9.2.0"
+ resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.2.0.tgz#2175af243196ec784dd532149a34e108fe0a7be6"
+ integrity sha512-KulBtFSibPXN3sFtbikdskOokPpkEYf+VSexd0Emklo8iu/RcL4in+drsA2Z+dk+yDGEi7+TWBB7zghopuTa+g==
+ dependencies:
+ "@sentry/core" "9.2.0"
+
+"@sentry-internal/feedback@9.2.0":
+ version "9.2.0"
+ resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.2.0.tgz#78460900596a679e94a40e8ef16d7775b063d0b4"
+ integrity sha512-3rl2uBoXkz2N+OVzMkOQVK2MakC+U0lPh4FqBVOcAYiqovGnzobgpvdP5Um+lM/00oCtkJ1+8KjbW1ZnV1/cKQ==
+ dependencies:
+ "@sentry/core" "9.2.0"
+
+"@sentry-internal/replay-canvas@9.2.0":
+ version "9.2.0"
+ resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.2.0.tgz#1ae21743c9e5fe597a66539f2ea3e20fc1168968"
+ integrity sha512-+q5dmEzMXs8/Fcl74mf8D8t3/W1pYPVse6jt0dNzo5o1z/LWgWY0LlImmlPU1QBIlUzB6VZkgfaKen8wZdcOVA==
+ dependencies:
+ "@sentry-internal/replay" "9.2.0"
+ "@sentry/core" "9.2.0"
+
+"@sentry-internal/replay@9.2.0":
+ version "9.2.0"
+ resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.2.0.tgz#cb84e232e6af91259dfe1a638e0d1578616239e6"
+ integrity sha512-/7YS9BNPOSuuguT2/yS103vXmAKe13j+B0lreRgWPxUnfSsCQvmJ4UNuat61qJNl1MbJDCurG5eN94QwRqg6kA==
+ dependencies:
+ "@sentry-internal/browser-utils" "9.2.0"
+ "@sentry/core" "9.2.0"
+
+"@sentry/babel-plugin-component-annotate@2.22.6":
+ version "2.22.6"
+ resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.6.tgz#829d6caf2c95c1c46108336de4e1049e6521435e"
+ integrity sha512-V2g1Y1I5eSe7dtUVMBvAJr8BaLRr4CLrgNgtPaZyMT4Rnps82SrZ5zqmEkLXPumlXhLUWR6qzoMNN2u+RXVXfQ==
+
+"@sentry/babel-plugin-component-annotate@3.1.2":
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.1.2.tgz#5497ca5adbe775955e96c566511a0bed3ab0a3ce"
+ integrity sha512-5h2WXRJ6swKA0TwxHHryC8M2QyOfS9QhTAL6ElPfkEYe9HhJieXmxsDpyspbqAa26ccnCUcmwE5vL34jAjt4sQ==
+
+"@sentry/browser@9.2.0":
+ version "9.2.0"
+ resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.2.0.tgz#b8ca8c5750127477b154ca893485e06a26f1a7dd"
+ integrity sha512-U4JpFq3eYrXmuTSzG+rUgNr37FSok0nJlcygVqrTesh8+wV48D8maEbiKJ0txjaJ2h1E5rK09zutSPSS3Bp4uA==
+ dependencies:
+ "@sentry-internal/browser-utils" "9.2.0"
+ "@sentry-internal/feedback" "9.2.0"
+ "@sentry-internal/replay" "9.2.0"
+ "@sentry-internal/replay-canvas" "9.2.0"
+ "@sentry/core" "9.2.0"
+
+"@sentry/bundler-plugin-core@2.22.6":
+ version "2.22.6"
+ resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.22.6.tgz#a1ea1fd43700a3ece9e7db016997e79a2782b87d"
+ integrity sha512-1esQdgSUCww9XAntO4pr7uAM5cfGhLsgTK9MEwAKNfvpMYJi9NUTYa3A7AZmdA8V6107Lo4OD7peIPrDRbaDCg==
+ dependencies:
+ "@babel/core" "^7.18.5"
+ "@sentry/babel-plugin-component-annotate" "2.22.6"
+ "@sentry/cli" "^2.36.1"
+ dotenv "^16.3.1"
+ find-up "^5.0.0"
+ glob "^9.3.2"
+ magic-string "0.30.8"
+ unplugin "1.0.1"
+
+"@sentry/bundler-plugin-core@3.1.2":
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.1.2.tgz#29e4e686c5893b41a0d98a1bef6f0315a610bd59"
+ integrity sha512-lqOCvmOPzKiQenIMhmm5/mwCntwFy0dPZbVD28Dnr3MXpT1rIBg1HXjfnqQWFlMRbL9haSsWiY/TQyR/6b30YA==
+ dependencies:
+ "@babel/core" "^7.18.5"
+ "@sentry/babel-plugin-component-annotate" "3.1.2"
+ "@sentry/cli" "2.41.1"
+ dotenv "^16.3.1"
+ find-up "^5.0.0"
+ glob "^9.3.2"
+ magic-string "0.30.8"
+ unplugin "1.0.1"
+
+"@sentry/cli-darwin@2.41.1":
+ version "2.41.1"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.41.1.tgz#ca7e12bf1ad59bc2df35868ae98abc8869108efa"
+ integrity sha512-7pS3pu/SuhE6jOn3wptstAg6B5nUP878O6s+2svT7b5fKNfYUi/6NPK6dAveh2Ca0rwVq40TO4YFJabWMgTpdQ==
+
+"@sentry/cli-darwin@2.42.2":
+ version "2.42.2"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.42.2.tgz#a32a4f226e717122b37d9969e8d4d0e14779f720"
+ integrity sha512-GtJSuxER7Vrp1IpxdUyRZzcckzMnb4N5KTW7sbTwUiwqARRo+wxS+gczYrS8tdgtmXs5XYhzhs+t4d52ITHMIg==
+
+"@sentry/cli-linux-arm64@2.41.1":
+ version "2.41.1"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.41.1.tgz#948e8af8290418b1562db3531db08e69e39d74bb"
+ integrity sha512-EzYCEnnENBnS5kpNW+2dBcrPZn1MVfywh2joGVQZTpmgDL5YFJ59VOd+K0XuEwqgFI8BSNI14KXZ75s4DD1/Vw==
+
+"@sentry/cli-linux-arm64@2.42.2":
+ version "2.42.2"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.42.2.tgz#1c06c83ff21f51ec23acf5be3b1f8c7553bf86b1"
+ integrity sha512-BOxzI7sgEU5Dhq3o4SblFXdE9zScpz6EXc5Zwr1UDZvzgXZGosUtKVc7d1LmkrHP8Q2o18HcDWtF3WvJRb5Zpw==
+
+"@sentry/cli-linux-arm@2.41.1":
+ version "2.41.1"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.41.1.tgz#1e5fa971ae8dfb3ea5564c8503b4e635ae6aed8a"
+ integrity sha512-wNUvquD6qjOCczvuBGf9OiD29nuQ6yf8zzfyPJa5Bdx1QXuteKsKb6HBrMwuIR3liyuu0duzHd+H/+p1n541Hg==
+
+"@sentry/cli-linux-arm@2.42.2":
+ version "2.42.2"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.42.2.tgz#00cadc359ae3c051efb3e63873c033c61dbd1ca1"
+ integrity sha512-7udCw+YL9lwq+9eL3WLspvnuG+k5Icg92YE7zsteTzWLwgPVzaxeZD2f8hwhsu+wmL+jNqbpCRmktPteh3i2mg==
+
+"@sentry/cli-linux-i686@2.41.1":
+ version "2.41.1"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.41.1.tgz#3f01aff314f2ad8fd761f3e6e807a5ec09ae4eb4"
+ integrity sha512-urpQCWrdYnSAsZY3udttuMV88wTJzKZL10xsrp7sjD/Hd+O6qSLVLkxebIlxts70jMLLFHYrQ2bkRg5kKuX6Fg==
+
+"@sentry/cli-linux-i686@2.42.2":
+ version "2.42.2"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.42.2.tgz#3b817b715dd806c20dfbffd539725ad8089c310a"
+ integrity sha512-Sw/dQp5ZPvKnq3/y7wIJyxTUJYPGoTX/YeMbDs8BzDlu9to2LWV3K3r7hE7W1Lpbaw4tSquUHiQjP5QHCOS7aQ==
+
+"@sentry/cli-linux-x64@2.41.1":
+ version "2.41.1"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.41.1.tgz#30dbf966a4b4c1721ffccd901dfcb6f967db073d"
+ integrity sha512-ZqpYwHXAaK4MMEFlyaLYr6mJTmpy9qP6n30jGhLTW7kHKS3s6GPLCSlNmIfeClrInEt0963fM633ZRnXa04VPw==
+
+"@sentry/cli-linux-x64@2.42.2":
+ version "2.42.2"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.42.2.tgz#ddf906bc3071cc79ce6e633eddcb76bb9068e688"
+ integrity sha512-mU4zUspAal6TIwlNLBV5oq6yYqiENnCWSxtSQVzWs0Jyq97wtqGNG9U+QrnwjJZ+ta/hvye9fvL2X25D/RxHQw==
+
+"@sentry/cli-win32-i686@2.41.1":
+ version "2.41.1"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.41.1.tgz#f88eeb5d2d4ee46c38d8616ae1eb484108ea71c2"
+ integrity sha512-AuRimCeVsx99DIOr9cwdYBHk39tlmAuPDdy2r16iNzY0InXs4xOys4gGzM7N4vlFQvFkzuc778Su0HkfasgprA==
+
+"@sentry/cli-win32-i686@2.42.2":
+ version "2.42.2"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.42.2.tgz#9036085c7c6ce455ad45fda411c55ff39c06eb95"
+ integrity sha512-iHvFHPGqgJMNqXJoQpqttfsv2GI3cGodeTq4aoVLU/BT3+hXzbV0x1VpvvEhncJkDgDicJpFLM8sEPHb3b8abw==
+
+"@sentry/cli-win32-x64@2.41.1":
+ version "2.41.1"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.41.1.tgz#eefd95a2aa184adb464334e265b55a9142070f6f"
+ integrity sha512-6JcPvXGye61+wPp0xdzfc2YLE/Dcud8JdaK8VxLM3b/8+Em7E+UyliDu3uF8+YGUqizY5JYTd3fs17DC8DZhLw==
+
+"@sentry/cli-win32-x64@2.42.2":
+ version "2.42.2"
+ resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.42.2.tgz#7d6464b63f32c9f97fff428f246b1f039b402233"
+ integrity sha512-vPPGHjYoaGmfrU7xhfFxG7qlTBacroz5NdT+0FmDn6692D8IvpNXl1K+eV3Kag44ipJBBeR8g1HRJyx/F/9ACw==
+
+"@sentry/cli@2.41.1":
+ version "2.41.1"
+ resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.41.1.tgz#a9467ca3ff4acfcdedec1565c9ff726b93758d29"
+ integrity sha512-0GVmDiTV7R1492wkVY4bGcfC0fSmRmQjuxaaPI8CIV9B2VP9pBVCUizi1mevXaaE4I3fM60LI+XYrKFEneuVog==
+ dependencies:
+ https-proxy-agent "^5.0.0"
+ node-fetch "^2.6.7"
+ progress "^2.0.3"
+ proxy-from-env "^1.1.0"
+ which "^2.0.2"
+ optionalDependencies:
+ "@sentry/cli-darwin" "2.41.1"
+ "@sentry/cli-linux-arm" "2.41.1"
+ "@sentry/cli-linux-arm64" "2.41.1"
+ "@sentry/cli-linux-i686" "2.41.1"
+ "@sentry/cli-linux-x64" "2.41.1"
+ "@sentry/cli-win32-i686" "2.41.1"
+ "@sentry/cli-win32-x64" "2.41.1"
+
+"@sentry/cli@^2.36.1":
+ version "2.42.2"
+ resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.42.2.tgz#8173df4d057d600a9ef0cf1e9b42b0c6607b46e4"
+ integrity sha512-spb7S/RUumCGyiSTg8DlrCX4bivCNmU/A1hcfkwuciTFGu8l5CDc2I6jJWWZw8/0enDGxuj5XujgXvU5tr4bxg==
+ dependencies:
+ https-proxy-agent "^5.0.0"
+ node-fetch "^2.6.7"
+ progress "^2.0.3"
+ proxy-from-env "^1.1.0"
+ which "^2.0.2"
+ optionalDependencies:
+ "@sentry/cli-darwin" "2.42.2"
+ "@sentry/cli-linux-arm" "2.42.2"
+ "@sentry/cli-linux-arm64" "2.42.2"
+ "@sentry/cli-linux-i686" "2.42.2"
+ "@sentry/cli-linux-x64" "2.42.2"
+ "@sentry/cli-win32-i686" "2.42.2"
+ "@sentry/cli-win32-x64" "2.42.2"
+
+"@sentry/core@9.2.0":
+ version "9.2.0"
+ resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.2.0.tgz#75ca124f2d612e52b4ab44f64e2f75321af703bf"
+ integrity sha512-REnEuneWyv3DkZfr0ZCQOZRCkBxUuWMY7aJ7BwWU9t3CFRUIPO0ePiXb2eZJEkDtalJK+m9pSTDUbChtrzQmLA==
+
+"@sentry/node@9.2.0":
+ version "9.2.0"
+ resolved "https://registry.yarnpkg.com/@sentry/node/-/node-9.2.0.tgz#7ffc9cdfdfcf5cce404119d0418a2246e4f4a242"
+ integrity sha512-QDOCIs8hTnwPE34FwYL1oIQneqpqyl85MOEfHnv1K7WZ4XYaHMvlJi1vSDr155buFC9K6JkINTw5yJmU1Pi5mA==
+ dependencies:
+ "@opentelemetry/api" "^1.9.0"
+ "@opentelemetry/context-async-hooks" "^1.30.1"
+ "@opentelemetry/core" "^1.30.1"
+ "@opentelemetry/instrumentation" "^0.57.1"
+ "@opentelemetry/instrumentation-amqplib" "^0.46.0"
+ "@opentelemetry/instrumentation-connect" "0.43.0"
+ "@opentelemetry/instrumentation-dataloader" "0.16.0"
+ "@opentelemetry/instrumentation-express" "0.47.0"
+ "@opentelemetry/instrumentation-fastify" "0.44.1"
+ "@opentelemetry/instrumentation-fs" "0.19.0"
+ "@opentelemetry/instrumentation-generic-pool" "0.43.0"
+ "@opentelemetry/instrumentation-graphql" "0.47.0"
+ "@opentelemetry/instrumentation-hapi" "0.45.1"
+ "@opentelemetry/instrumentation-http" "0.57.1"
+ "@opentelemetry/instrumentation-ioredis" "0.47.0"
+ "@opentelemetry/instrumentation-kafkajs" "0.7.0"
+ "@opentelemetry/instrumentation-knex" "0.44.0"
+ "@opentelemetry/instrumentation-koa" "0.47.0"
+ "@opentelemetry/instrumentation-lru-memoizer" "0.44.0"
+ "@opentelemetry/instrumentation-mongodb" "0.51.0"
+ "@opentelemetry/instrumentation-mongoose" "0.46.0"
+ "@opentelemetry/instrumentation-mysql" "0.45.0"
+ "@opentelemetry/instrumentation-mysql2" "0.45.0"
+ "@opentelemetry/instrumentation-pg" "0.51.0"
+ "@opentelemetry/instrumentation-redis-4" "0.46.0"
+ "@opentelemetry/instrumentation-tedious" "0.18.0"
+ "@opentelemetry/instrumentation-undici" "0.10.0"
+ "@opentelemetry/resources" "^1.30.1"
+ "@opentelemetry/sdk-trace-base" "^1.30.1"
+ "@opentelemetry/semantic-conventions" "^1.28.0"
+ "@prisma/instrumentation" "6.2.1"
+ "@sentry/core" "9.2.0"
+ "@sentry/opentelemetry" "9.2.0"
+ import-in-the-middle "^1.12.0"
+
+"@sentry/nuxt@^9.2.0":
+ version "9.2.0"
+ resolved "https://registry.yarnpkg.com/@sentry/nuxt/-/nuxt-9.2.0.tgz#38fcbdfccc3128471995a60cfddb05760b3709a8"
+ integrity sha512-qE+srQXE+L3oo3YJU/A9UHdT2F5RQi6ByVo8crE7lAf0C/0gKkz1xmTxmQvxEetgWrGDg3/sBSCu7y5m7a27Eg==
+ dependencies:
+ "@nuxt/kit" "^3.13.2"
+ "@sentry/browser" "9.2.0"
+ "@sentry/core" "9.2.0"
+ "@sentry/node" "9.2.0"
+ "@sentry/opentelemetry" "9.2.0"
+ "@sentry/rollup-plugin" "3.1.2"
+ "@sentry/vite-plugin" "2.22.6"
+ "@sentry/vue" "9.2.0"
+
+"@sentry/opentelemetry@9.2.0":
+ version "9.2.0"
+ resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-9.2.0.tgz#be51122dfa4e47858da8854618b345df6c0b9ee3"
+ integrity sha512-ksd3M+KXuHt5vsPcqyy77YxVP0yb27J2LD19fasiybOPedb90XjynEk29zVBmW2iEPt8Ddw55FKDNVnHFEbUjw==
+ dependencies:
+ "@sentry/core" "9.2.0"
+
+"@sentry/rollup-plugin@3.1.2":
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/@sentry/rollup-plugin/-/rollup-plugin-3.1.2.tgz#d1ed4eeb558e10260bf0e7f292f9ad6baf22a98c"
+ integrity sha512-CVUsfQkL8REOGuyaPX7BzccZoq+wce05gQW3dG4PcXNPQeKTPRpC89NLcCDJijJa08yvC0DF0wsWRhlFWM89kQ==
+ dependencies:
+ "@sentry/bundler-plugin-core" "3.1.2"
+ unplugin "1.0.1"
+
+"@sentry/vite-plugin@2.22.6":
+ version "2.22.6"
+ resolved "https://registry.yarnpkg.com/@sentry/vite-plugin/-/vite-plugin-2.22.6.tgz#d08a1ede05f137636d5b3c61845d24c0114f0d76"
+ integrity sha512-zIieP1VLWQb3wUjFJlwOAoaaJygJhXeUoGd0e/Ha2RLb2eW2S+4gjf6y6NqyY71tZ74LYVZKg/4prB6FAZSMXQ==
+ dependencies:
+ "@sentry/bundler-plugin-core" "2.22.6"
+ unplugin "1.0.1"
+
+"@sentry/vue@9.2.0":
+ version "9.2.0"
+ resolved "https://registry.yarnpkg.com/@sentry/vue/-/vue-9.2.0.tgz#356237ebb047a22925505371a35715a60128df63"
+ integrity sha512-p4e8xObBnuN40S4hwcQfU/THBxaCOCGScs3N4ti6NLFMSIpdSVJK0/E11Ic9OS4JxM+W8z9GvcoeLHUowxVe2g==
+ dependencies:
+ "@sentry/browser" "9.2.0"
+ "@sentry/core" "9.2.0"
+
"@sindresorhus/merge-streams@^2.1.0":
version "2.3.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz#719df7fb41766bc143369eaa0dd56d8dc87c9958"
@@ -1193,6 +1790,13 @@
resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
+"@types/connect@3.4.36":
+ version "3.4.36"
+ resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.36.tgz#e511558c15a39cb29bd5357eebb57bd1459cd1ab"
+ integrity sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==
+ dependencies:
+ "@types/node" "*"
+
"@types/estree@*", "@types/estree@1.0.6", "@types/estree@^1.0.0":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
@@ -1205,6 +1809,13 @@
dependencies:
"@types/node" "*"
+"@types/mysql@2.15.26":
+ version "2.15.26"
+ resolved "https://registry.yarnpkg.com/@types/mysql/-/mysql-2.15.26.tgz#f0de1484b9e2354d587e7d2bd17a873cc8300836"
+ integrity sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==
+ dependencies:
+ "@types/node" "*"
+
"@types/node@*":
version "22.13.5"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.5.tgz#23add1d71acddab2c6a4d31db89c0f98d330b511"
@@ -1217,11 +1828,48 @@
resolved "https://registry.yarnpkg.com/@types/parse-path/-/parse-path-7.0.3.tgz#cec2da2834ab58eb2eb579122d9a1fc13bd7ef36"
integrity sha512-LriObC2+KYZD3FzCrgWGv/qufdUy4eXrxcLgQMfYXgPbLIecKIsVBaQgUPmxSSLcjmYbDTQbMgr6qr6l/eb7Bg==
+"@types/pg-pool@2.0.6":
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/@types/pg-pool/-/pg-pool-2.0.6.tgz#1376d9dc5aec4bb2ec67ce28d7e9858227403c77"
+ integrity sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==
+ dependencies:
+ "@types/pg" "*"
+
+"@types/pg@*":
+ version "8.11.11"
+ resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.11.11.tgz#3bdce0580e521a62a62339a53d110458d9eae6df"
+ integrity sha512-kGT1qKM8wJQ5qlawUrEkXgvMSXoV213KfMGXcwfDwUIfUHXqXYXOfS1nE1LINRJVVVx5wCm70XnFlMHaIcQAfw==
+ dependencies:
+ "@types/node" "*"
+ pg-protocol "*"
+ pg-types "^4.0.1"
+
+"@types/pg@8.6.1":
+ version "8.6.1"
+ resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.6.1.tgz#099450b8dc977e8197a44f5229cedef95c8747f9"
+ integrity sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==
+ dependencies:
+ "@types/node" "*"
+ pg-protocol "*"
+ pg-types "^2.2.0"
+
"@types/resolve@1.20.2":
version "1.20.2"
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975"
integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==
+"@types/shimmer@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.2.0.tgz#9b706af96fa06416828842397a70dfbbf1c14ded"
+ integrity sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==
+
+"@types/tedious@^4.0.14":
+ version "4.0.14"
+ resolved "https://registry.yarnpkg.com/@types/tedious/-/tedious-4.0.14.tgz#868118e7a67808258c05158e9cad89ca58a2aec1"
+ integrity sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==
+ dependencies:
+ "@types/node" "*"
+
"@types/web-bluetooth@^0.0.20":
version "0.0.20"
resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz#f066abfcd1cbe66267cdbbf0de010d8a41b41597"
@@ -1535,11 +2183,18 @@ acorn-import-attributes@^1.9.5:
resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef"
integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==
-acorn@8.14.0, acorn@^8.14.0, acorn@^8.6.0, acorn@^8.8.2:
+acorn@8.14.0, acorn@^8.14.0, acorn@^8.6.0, acorn@^8.8.1, acorn@^8.8.2:
version "8.14.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0"
integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==
+agent-base@6:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
+ integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
+ dependencies:
+ debug "4"
+
agent-base@^7.1.2:
version "7.1.3"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.3.tgz#29435eb821bc4194633a5b89e5bc4703bafc25a1"
@@ -1824,7 +2479,7 @@ change-case@^5.4.4:
resolved "https://registry.yarnpkg.com/change-case/-/change-case-5.4.4.tgz#0d52b507d8fb8f204343432381d1a6d7bff97a02"
integrity sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==
-chokidar@^3.5.1, chokidar@^3.6.0:
+chokidar@^3.5.1, chokidar@^3.5.3, chokidar@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
@@ -1863,6 +2518,11 @@ citty@^0.1.5, citty@^0.1.6:
dependencies:
consola "^3.2.3"
+cjs-module-lexer@^1.2.2:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz#0f79731eb8cfe1ec72acd4066efac9d61991b00d"
+ integrity sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==
+
clipboardy@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-4.0.0.tgz#e73ced93a76d19dd379ebf1f297565426dffdca1"
@@ -2276,7 +2936,7 @@ dot-prop@^9.0.0:
dependencies:
type-fest "^4.18.2"
-dotenv@^16.4.5, dotenv@^16.4.7:
+dotenv@^16.3.1, dotenv@^16.4.5, dotenv@^16.4.7:
version "16.4.7"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26"
integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==
@@ -2559,6 +3219,14 @@ fill-range@^7.1.1:
dependencies:
to-regex-range "^5.0.1"
+find-up@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+ integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+ dependencies:
+ locate-path "^6.0.0"
+ path-exists "^4.0.0"
+
flatted@^3.3.2:
version "3.3.3"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358"
@@ -2580,6 +3248,11 @@ foreground-child@^3.1.0:
cross-spawn "^7.0.6"
signal-exit "^4.0.1"
+forwarded-parse@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/forwarded-parse/-/forwarded-parse-2.1.2.tgz#08511eddaaa2ddfd56ba11138eee7df117a09325"
+ integrity sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==
+
fraction.js@^4.3.7:
version "4.3.7"
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
@@ -2715,6 +3388,16 @@ glob@^7.1.3:
once "^1.3.0"
path-is-absolute "^1.0.0"
+glob@^9.3.2:
+ version "9.3.5"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21"
+ integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==
+ dependencies:
+ fs.realpath "^1.0.0"
+ minimatch "^8.0.2"
+ minipass "^4.2.4"
+ path-scurry "^1.6.1"
+
global-directory@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/global-directory/-/global-directory-4.0.1.tgz#4d7ac7cfd2cb73f304c53b8810891748df5e361e"
@@ -2809,6 +3492,14 @@ http-shutdown@^1.2.2:
resolved "https://registry.yarnpkg.com/http-shutdown/-/http-shutdown-1.2.2.tgz#41bc78fc767637c4c95179bc492f312c0ae64c5f"
integrity sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==
+https-proxy-agent@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
+ integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
+ dependencies:
+ agent-base "6"
+ debug "4"
+
https-proxy-agent@^7.0.5:
version "7.0.6"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9"
@@ -2847,6 +3538,16 @@ image-meta@^0.2.1:
resolved "https://registry.yarnpkg.com/image-meta/-/image-meta-0.2.1.tgz#3a9eb9f0bfd2f767ca2b0720623c2e03742aa29f"
integrity sha512-K6acvFaelNxx8wc2VjbIzXKDVB0Khs0QT35U6NkGfTdCmjLNcO2945m7RFNR9/RPVFm48hq7QPzK8uGH18HCGw==
+import-in-the-middle@^1.12.0, import-in-the-middle@^1.8.1:
+ version "1.13.0"
+ resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.13.0.tgz#e592583c3f53ff29c6079c0af31feab592ac6b2a"
+ integrity sha512-YG86SYDtrL/Yu8JgfWb7kjQ0myLeT1whw6fs/ZHFkXFcbk9zJU9lOCsSJHpvaPumU11nN3US7NW6x1YTk+HrUA==
+ dependencies:
+ acorn "^8.14.0"
+ acorn-import-attributes "^1.9.5"
+ cjs-module-lexer "^1.2.2"
+ module-details-from-path "^1.0.3"
+
impound@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/impound/-/impound-0.2.0.tgz#d24d6dd8330f380e8e71c254e8b29d3a2c4fe520"
@@ -3182,6 +3883,13 @@ local-pkg@^1.0.0:
mlly "^1.7.3"
pkg-types "^1.3.0"
+locate-path@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
+ integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+ dependencies:
+ p-locate "^5.0.0"
+
lodash.defaults@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
@@ -3231,6 +3939,13 @@ magic-string-ast@^0.7.0:
dependencies:
magic-string "^0.30.17"
+magic-string@0.30.8:
+ version "0.30.8"
+ resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.8.tgz#14e8624246d2bedba70d5462aa99ac9681844613"
+ integrity sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==
+ dependencies:
+ "@jridgewell/sourcemap-codec" "^1.4.15"
+
magic-string@^0.30.11, magic-string@^0.30.12, magic-string@^0.30.17, magic-string@^0.30.3, magic-string@^0.30.4, magic-string@^0.30.8:
version "0.30.17"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453"
@@ -3309,6 +4024,13 @@ minimatch@^5.0.1, minimatch@^5.1.0:
dependencies:
brace-expansion "^2.0.1"
+minimatch@^8.0.2:
+ version "8.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229"
+ integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==
+ dependencies:
+ brace-expansion "^2.0.1"
+
minimatch@^9.0.4:
version "9.0.5"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5"
@@ -3323,6 +4045,11 @@ minipass@^3.0.0:
dependencies:
yallist "^4.0.0"
+minipass@^4.2.4:
+ version "4.2.8"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a"
+ integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==
+
minipass@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d"
@@ -3374,6 +4101,11 @@ mlly@^1.3.0, mlly@^1.6.1, mlly@^1.7.1, mlly@^1.7.2, mlly@^1.7.3, mlly@^1.7.4:
pkg-types "^1.3.0"
ufo "^1.5.4"
+module-details-from-path@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b"
+ integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==
+
moment@^2.30.1:
version "2.30.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae"
@@ -3657,6 +4389,11 @@ nypm@^0.5.2, nypm@^0.5.4:
tinyexec "^0.3.2"
ufo "^1.5.4"
+obuf@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
+ integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
+
ofetch@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.4.1.tgz#b6bf6b0d75ba616cef6519dd8b6385a8bae480ec"
@@ -3728,6 +4465,20 @@ openapi-typescript@^7.4.2:
supports-color "^9.4.0"
yargs-parser "^21.1.1"
+p-limit@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+ integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+ dependencies:
+ yocto-queue "^0.1.0"
+
+p-locate@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
+ integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+ dependencies:
+ p-limit "^3.0.2"
+
package-json-from-dist@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505"
@@ -3780,6 +4531,11 @@ parseurl@~1.3.3:
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
@@ -3800,7 +4556,7 @@ path-parse@^1.0.7:
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
-path-scurry@^1.11.1:
+path-scurry@^1.11.1, path-scurry@^1.6.1:
version "1.11.1"
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2"
integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==
@@ -3828,6 +4584,45 @@ perfect-debounce@^1.0.0:
resolved "https://registry.yarnpkg.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz#9c2e8bc30b169cc984a58b7d5b28049839591d2a"
integrity sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==
+pg-int8@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c"
+ integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==
+
+pg-numeric@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/pg-numeric/-/pg-numeric-1.0.2.tgz#816d9a44026086ae8ae74839acd6a09b0636aa3a"
+ integrity sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==
+
+pg-protocol@*:
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.7.1.tgz#aad61a6f927b51e89dcf721408b76c0e536d43dc"
+ integrity sha512-gjTHWGYWsEgy9MsY0Gp6ZJxV24IjDqdpTW7Eh0x+WfJLFsm/TJx1MzL6T0D88mBvkpxotCQ6TwW6N+Kko7lhgQ==
+
+pg-types@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3"
+ integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==
+ 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"
+
+pg-types@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-4.0.2.tgz#399209a57c326f162461faa870145bb0f918b76d"
+ integrity sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==
+ 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"
+
picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
@@ -4105,6 +4900,55 @@ postcss@^8.4.48, postcss@^8.5.1, postcss@^8.5.3:
picocolors "^1.1.1"
source-map-js "^1.2.1"
+postgres-array@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e"
+ integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==
+
+postgres-array@~3.0.1:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-3.0.2.tgz#68d6182cb0f7f152a7e60dc6a6889ed74b0a5f98"
+ integrity sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==
+
+postgres-bytea@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35"
+ integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==
+
+postgres-bytea@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-3.0.0.tgz#9048dc461ac7ba70a6a42d109221619ecd1cb089"
+ integrity sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==
+ dependencies:
+ obuf "~1.1.2"
+
+postgres-date@~1.0.4:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8"
+ integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==
+
+postgres-date@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-2.1.0.tgz#b85d3c1fb6fb3c6c8db1e9942a13a3bf625189d0"
+ integrity sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==
+
+postgres-interval@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695"
+ integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==
+ dependencies:
+ xtend "^4.0.0"
+
+postgres-interval@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-3.0.0.tgz#baf7a8b3ebab19b7f38f07566c7aab0962f0c86a"
+ integrity sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==
+
+postgres-range@^1.1.1:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/postgres-range/-/postgres-range-1.1.4.tgz#a59c5f9520909bcec5e63e8cf913a92e4c952863"
+ integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==
+
pretty-bytes@^6.1.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-6.1.1.tgz#38cd6bb46f47afbf667c202cfc754bffd2016a3b"
@@ -4120,6 +4964,11 @@ process@^0.11.10:
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
+progress@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
+ integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
+
prompts@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
@@ -4133,6 +4982,11 @@ protocols@^2.0.0, protocols@^2.0.1:
resolved "https://registry.yarnpkg.com/protocols/-/protocols-2.0.2.tgz#822e8fcdcb3df5356538b3e91bfd890b067fd0a4"
integrity sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==
+proxy-from-env@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
+ integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
+
queue-microtask@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
@@ -4233,12 +5087,21 @@ require-from-string@^2.0.2:
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+require-in-the-middle@^7.1.1:
+ version "7.5.2"
+ resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz#dc25b148affad42e570cf0e41ba30dc00f1703ec"
+ integrity sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==
+ dependencies:
+ debug "^4.3.5"
+ module-details-from-path "^1.0.3"
+ resolve "^1.22.8"
+
resolve-from@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
-resolve@^1.22.1:
+resolve@^1.22.1, resolve@^1.22.8:
version "1.22.10"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39"
integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==
@@ -4334,7 +5197,7 @@ semver@^6.3.1:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
-semver@^7.3.4, semver@^7.5.3, semver@^7.6.3, semver@^7.7.1:
+semver@^7.3.4, semver@^7.5.2, semver@^7.5.3, semver@^7.6.3, semver@^7.7.1:
version "7.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f"
integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
@@ -4404,6 +5267,11 @@ shell-quote@^1.8.1:
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.2.tgz#d2d83e057959d53ec261311e9e9b8f51dcb2934a"
integrity sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==
+shimmer@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337"
+ integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==
+
signal-exit@^3.0.7:
version "3.0.7"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
@@ -4896,6 +5764,16 @@ unplugin-vue-router@^0.11.2:
unplugin "2.1.2"
yaml "^2.7.0"
+unplugin@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.0.1.tgz#83b528b981cdcea1cad422a12cd02e695195ef3f"
+ integrity sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==
+ dependencies:
+ acorn "^8.8.1"
+ chokidar "^3.5.3"
+ webpack-sources "^3.2.3"
+ webpack-virtual-modules "^0.5.0"
+
unplugin@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-2.1.2.tgz#3a0939061c0076f1a8178e5d4223df63ee62c741"
@@ -5173,6 +6051,16 @@ webidl-conversions@^3.0.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
+webpack-sources@^3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
+ integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
+
+webpack-virtual-modules@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz#362f14738a56dae107937ab98ea7062e8bdd3b6c"
+ integrity sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==
+
webpack-virtual-modules@^0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz#057faa9065c8acf48f24cb57ac0e77739ab9a7e8"
@@ -5186,7 +6074,7 @@ whatwg-url@^5.0.0:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
-which@^2.0.1:
+which@^2.0.1, which@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
@@ -5247,6 +6135,11 @@ xmlhttprequest-ssl@~2.1.1:
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz#e9e8023b3f29ef34b97a859f584c5e6c61418e23"
integrity sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==
+xtend@^4.0.0:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
+ integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
+
y18n@^5.0.5:
version "5.0.8"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
@@ -5295,6 +6188,11 @@ yargs@^17.5.1:
y18n "^5.0.5"
yargs-parser "^21.1.1"
+yocto-queue@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+ integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
+
zhead@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/zhead/-/zhead-2.2.4.tgz#87cd1e2c3d2f465fa9f43b8db23f9716dfe6bed7"
From 1fa4c523bbbd3bd16a28b6edb1353eb7aeca09f1 Mon Sep 17 00:00:00 2001
From: ArabCoders
Date: Fri, 28 Feb 2025 00:44:02 +0300
Subject: [PATCH 08/10] intercept file response and add correct mime-type
---
app/library/HttpAPI.py | 19 +++++++++++++++++++
ui/layouts/default.vue | 8 +++++++-
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/app/library/HttpAPI.py b/app/library/HttpAPI.py
index c8ac7162..5f276f45 100644
--- a/app/library/HttpAPI.py
+++ b/app/library/HttpAPI.py
@@ -119,6 +119,7 @@ class HttpAPI(Common):
HttpAPI: The instance of the HttpAPI.
"""
+ app.middlewares.append(HttpAPI.middle_wares())
if self.config.auth_username and self.config.auth_password:
app.middlewares.append(HttpAPI.basic_auth(self.config.auth_username, self.config.auth_password))
@@ -310,6 +311,24 @@ class HttpAPI(Common):
return middleware_handler
+ @staticmethod
+ def middle_wares() -> Awaitable:
+ @web.middleware
+ async def middleware_handler(request: Request, handler: RequestHandler) -> Response:
+ response = await handler(request)
+
+ if isinstance(response, web.FileResponse):
+ try:
+ ff_info = await ffprobe(response._path)
+ mime_type = get_mime_type(ff_info.get("metadata", {}), response._path)
+ response.content_type = mime_type
+ except Exception:
+ pass
+
+ return response
+
+ return middleware_handler
+
@route("OPTIONS", "/{path:.*}")
async def add_coors(self, _: Request) -> Response:
"""
diff --git a/ui/layouts/default.vue b/ui/layouts/default.vue
index 28eec019..fdc7bcc8 100644
--- a/ui/layouts/default.vue
+++ b/ui/layouts/default.vue
@@ -145,7 +145,13 @@ const applyPreferredColorScheme = scheme => {
}
}
-watch(() => config.app.sentry_dsn, dsn => dsn ? Sentry.init({ dsn: dsn }) : null)
+watch(() => config.app.sentry_dsn, dsn => {
+ if (!dsn) {
+ return
+ }
+ console.warn('Loading sentry module.')
+ Sentry.init({ dsn: dsn })
+})
onMounted(async () => {
try {
From e847fea2dd0faa8bcc4da585fbefc8408df0ca3e Mon Sep 17 00:00:00 2001
From: ArabCoders
Date: Fri, 28 Feb 2025 01:06:58 +0300
Subject: [PATCH 09/10] for iOS devices fallback directly to m3u8
---
ui/components/VideoPlayer.vue | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/ui/components/VideoPlayer.vue b/ui/components/VideoPlayer.vue
index c1244291..63d0e18c 100644
--- a/ui/components/VideoPlayer.vue
+++ b/ui/components/VideoPlayer.vue
@@ -52,6 +52,7 @@ const thumbnail = ref('')
const artist = ref('')
const title = ref('')
const isAudio = ref(false)
+const isApple = /(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent)
let player = null;
let hls = null;
@@ -70,8 +71,8 @@ onMounted(async () => {
}
sources.value.push({
- src: makeDownload(config, props.item, 'api/download'),
- type: response.mimetype,
+ src: makeDownload(config, props.item, isApple ? 'm3u8' : 'api/download'),
+ type: isApple ? response.mimetype : 'application/x-mpegURL',
onerror: e => src_error(e),
})
@@ -100,7 +101,7 @@ onMounted(async () => {
})
})
- if (/(iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent)) {
+ if (isApple) {
document.documentElement.style.setProperty('--webkit-text-track-display', 'block');
}
From f0836ddd7754ddd1e3bd06b9efb222d4dc019d21 Mon Sep 17 00:00:00 2001
From: ArabCoders
Date: Fri, 28 Feb 2025 01:21:45 +0300
Subject: [PATCH 10/10] apple like to be snowflake.
---
.vscode/launch.json | 1 -
app/library/Utils.py | 5 -----
ui/components/VideoPlayer.vue | 25 ++++++++++++++++++-------
3 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/.vscode/launch.json b/.vscode/launch.json
index da500c43..e2486ea9 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -10,7 +10,6 @@
"runtimeArgs": [
"run",
"dev",
- "--",
"--port",
"8082"
],
diff --git a/app/library/Utils.py b/app/library/Utils.py
index 7a986130..e2e472c2 100644
--- a/app/library/Utils.py
+++ b/app/library/Utils.py
@@ -576,12 +576,7 @@ def get_mime_type(metadata: dict, file_path: pathlib.Path) -> str:
"matroska": "video/x-matroska", # Default for MKV
"webm": "video/webm", # MKV can also be WebM
"mp4": "video/mp4",
- "mov": "video/quicktime",
- "avi": "video/x-msvideo",
- "flv": "video/x-flv",
- "ogg": "video/ogg",
"mpegts": "video/mp2t",
- "3gp": "video/3gpp",
}
# Check format_name against known formats
diff --git a/ui/components/VideoPlayer.vue b/ui/components/VideoPlayer.vue
index 63d0e18c..10812a07 100644
--- a/ui/components/VideoPlayer.vue
+++ b/ui/components/VideoPlayer.vue
@@ -28,7 +28,7 @@