Compare commits

...

11 Commits

Author SHA1 Message Date
Yeicor
9ca53bca61 fix issue with helpers 2024-03-09 12:48:22 +01:00
Yeicor
f1b04db24a small improvement for export 2024-03-09 12:05:40 +01:00
Yeicor
a304536536 Merge remote-tracking branch 'origin/master' 2024-03-09 11:47:31 +01:00
Yeicor
8b3d08826d small fix for pip 2024-03-09 11:47:23 +01:00
dependabot[bot]
40f424dd20 Bump typescript from 5.3.3 to 5.4.2 (#12)
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.3.3 to 5.4.2.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release.yml)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v5.3.3...v5.4.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-09 09:21:30 +00:00
dependabot[bot]
cb6c0acb63 Bump @types/node from 20.11.24 to 20.11.25 (#13)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.11.24 to 20.11.25.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-09 09:20:51 +00:00
dependabot[bot]
4ddc38f5c5 Bump vue-tsc from 2.0.5 to 2.0.6 (#11)
Bumps [vue-tsc](https://github.com/vuejs/language-tools/tree/HEAD/packages/tsc) from 2.0.5 to 2.0.6.
- [Release notes](https://github.com/vuejs/language-tools/releases)
- [Changelog](https://github.com/vuejs/language-tools/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vuejs/language-tools/commits/v2.0.6/packages/tsc)

---
updated-dependencies:
- dependency-name: vue-tsc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-09 09:20:21 +00:00
dependabot[bot]
f26d3a65a0 Bump vuetify from 3.5.7 to 3.5.8 (#10)
Bumps [vuetify](https://github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify) from 3.5.7 to 3.5.8.
- [Release notes](https://github.com/vuetifyjs/vuetify/releases)
- [Commits](https://github.com/vuetifyjs/vuetify/commits/v3.5.8/packages/vuetify)

---
updated-dependencies:
- dependency-name: vuetify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-09 09:20:10 +00:00
dependabot[bot]
b027819815 Bump terser from 5.28.1 to 5.29.1 (#9)
Bumps [terser](https://github.com/terser/terser) from 5.28.1 to 5.29.1.
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/compare/v5.28.1...v5.29.1)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-09 09:20:02 +00:00
Yeicor
768603b4d3 increase default request timeout 2024-03-07 20:56:51 +01:00
Yeicor
3e3730a4a5 faster multi-object load, faster updates and better orthographic camera at different scales 2024-03-07 20:49:27 +01:00
12 changed files with 136 additions and 106 deletions

View File

@@ -67,7 +67,7 @@ jobs:
python-version: "3.11"
cache: "poetry"
- run: "SKIP_BUILD_FRONTEND=true poetry install"
- run: "PYTHONPATH=yacv_server YACV_STOP_EARLY=true poetry run python example/object.py"
- run: "PYTHONPATH=yacv_server YACV_DISABLE_SERVER=true poetry run python example/object.py"
- run: "mv export/object.glb export/example.glb"
- uses: "actions/upload-artifact@v4"
with:

View File

@@ -1290,7 +1290,7 @@ third-party archives.
The following npm package may be included in this product:
- typescript@5.3.3
- typescript@5.4.2
This package contains the following license and notice below:
@@ -2408,7 +2408,7 @@ THE SOFTWARE.
The following npm package may be included in this product:
- vuetify@3.5.7
- vuetify@3.5.8
This package contains the following license and notice below:

View File

@@ -2,7 +2,8 @@ import os
import subprocess
if __name__ == "__main__":
if os.getenv('SKIP_BUILD_FRONTEND') is None:
# Building the frontend is optional
if os.getenv('SKIP_BUILD_FRONTEND') is None and os.path.exists('package.json'):
# When building the backend, make sure the frontend is built first
subprocess.run(['yarn', 'install'], check=True)
subprocess.run(['yarn', 'build', '--outDir', 'yacv_server/frontend'], check=True)

View File

@@ -27,7 +27,7 @@ export class NetworkManager extends EventTarget {
if (url.startsWith("dev+")) {
let baseUrl = new URL(url.slice(4));
baseUrl.searchParams.set("api_updates", "true");
this.monitorDevServer(baseUrl);
await this.monitorDevServer(baseUrl);
} else {
// Get the last part of the URL as the "name" of the model
let name = url.split("/").pop();
@@ -40,27 +40,51 @@ export class NetworkManager extends EventTarget {
}
}
private monitorDevServer(url: URL) {
// WARNING: This will spam the console logs with failed requests when the server is down
let eventSource = new EventSource(url);
eventSource.onmessage = (event) => {
let data = JSON.parse(event.data);
console.debug("WebSocket message", data);
let urlObj = new URL(url);
urlObj.searchParams.delete("api_updates");
urlObj.searchParams.set("api_object", data.name);
this.foundModel(data.name, data.hash, urlObj.toString());
};
eventSource.onerror = () => { // Retry after a very short delay
setTimeout(() => this.monitorDevServer(url), settings.monitorEveryMs);
private async monitorDevServer(url: URL) {
try {
// WARNING: This will spam the console logs with failed requests when the server is down
let response = await fetch(url.toString());
console.log("Monitoring", url.toString(), response);
if (response.status === 200) {
let lines = readLinesStreamings(response.body!.getReader());
for await (let line of lines) {
if (!line || !line.startsWith("data:")) continue;
let data = JSON.parse(line.slice(5));
console.debug("WebSocket message", data);
let urlObj = new URL(url);
urlObj.searchParams.delete("api_updates");
urlObj.searchParams.set("api_object", data.name);
this.foundModel(data.name, data.hash, urlObj.toString());
}
}
} catch (e) { // Ignore errors (retry very soon)
}
setTimeout(() => this.monitorDevServer(url), settings.monitorEveryMs);
return;
}
private foundModel(name: string, hash: string | null, url: string) {
let prevHash = this.knownObjectHashes[name];
// TODO: Detect and manage instances of the same object (same hash, different name)
if (!hash || hash !== prevHash) {
this.knownObjectHashes[name] = hash;
this.dispatchEvent(new NetworkUpdateEvent(name, url));
}
}
}
async function* readLinesStreamings(reader: ReadableStreamDefaultReader<Uint8Array>) {
let decoder = new TextDecoder();
let buffer = new Uint8Array();
while (true) {
let {value, done} = await reader.read();
if (done || !value) break;
buffer = new Uint8Array([...buffer, ...value]);
let text = decoder.decode(buffer);
let lines = text.split("\n");
for (let i = 0; i < lines.length - 1; i++) {
yield lines[i];
}
buffer = new Uint8Array([...buffer.slice(-1)]);
}
}

View File

@@ -20,7 +20,7 @@ export class SceneMgr {
if (name !== extrasNameValueHelpers) {
// Reload the helpers to fit the new model
// TODO: Only reload the helpers after a few milliseconds of no more models being added/removed
document = await this.reloadHelpers(sceneUrl, document);
await this.reloadHelpers(sceneUrl, document);
} else {
// Display the final fully loaded model
let displayStart = performance.now();

View File

@@ -50,12 +50,14 @@ function syncOrthoCamera(force: boolean) {
let perspectiveCam: PerspectiveCamera = (scene as any).__perspectiveCamera;
if (force || perspectiveCam && scene.camera != perspectiveCam) {
// Get zoom level from perspective camera
let dist = scene.getTarget().distanceToSquared(perspectiveCam.position);
let w = scene.aspect * dist ** 1.1 / 4000;
let h = dist ** 1.1 / 4000;
let lookAtCenter = scene.getTarget().clone().add(scene.target.position);
let perspectiveWidthAtCenter =
2 * Math.tan(perspectiveCam.fov * Math.PI / 180 / 2) * perspectiveCam.position.distanceTo(lookAtCenter);
let w = perspectiveWidthAtCenter;
let h = perspectiveWidthAtCenter / scene.aspect;
(scene as any).camera = new OrthographicCamera(-w, w, h, -h, perspectiveCam.near, perspectiveCam.far);
scene.camera.position.copy(perspectiveCam.position);
scene.camera.lookAt(scene.getTarget().clone().add(scene.target.position));
scene.camera.lookAt(lookAtCenter);
if (force) scene.queueRender() // Force rerender of model-viewer
requestAnimationFrame(() => syncOrthoCamera(false));
}

View File

@@ -1,6 +1,6 @@
{
"name": "yet-another-cad-viewer",
"version": "0.3.0",
"version": "0.4.3",
"description": "",
"license": "MIT",
"author": "Yeicor <4929005+Yeicor@users.noreply.github.com>",
@@ -23,11 +23,11 @@
"three": "^0.160.1",
"three-orientation-gizmo": "https://github.com/jrj2211/three-orientation-gizmo",
"vue": "^3.4.21",
"vuetify": "^3.5.7"
"vuetify": "^3.5.8"
},
"devDependencies": {
"@tsconfig/node20": "^20.1.2",
"@types/node": "^20.11.24",
"@types/node": "^20.11.25",
"@types/three": "^0.160.0",
"@vitejs/plugin-vue": "^5.0.3",
"@vitejs/plugin-vue-jsx": "^3.1.0",
@@ -36,9 +36,9 @@
"commander": "^12.0.0",
"generate-license-file": "^3.0.1",
"npm-run-all2": "^6.1.1",
"terser": "^5.28.1",
"typescript": "~5.3.0",
"terser": "^5.29.1",
"typescript": "~5.4.2",
"vite": "^5.1.5",
"vue-tsc": "^2.0.5"
"vue-tsc": "^2.0.6"
}
}

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "yacv-server"
version = "0.3.0" # TODO: Update automatically by CI on release (also for package.json!)
version = "0.4.3" # TODO: Update automatically by CI on release (also for package.json!)
description = "Yet Another CAD Viewer (server)"
authors = ["Yeicor <4929005+Yeicor@users.noreply.github.com>"]
license = "MIT"

View File

@@ -103,9 +103,10 @@ class GLTFMgr:
indices_blob = indices.flatten().tobytes()
# Check that all vertices are referenced by the indices
assert indices.max() == len(vertices) - 1, f"{indices.max()} != {len(vertices) - 1}"
assert indices.min() == 0
assert np.unique(indices.flatten()).size == len(vertices)
# This can happen on broken faces like on some fonts
# assert indices.max() == len(vertices) - 1, f"{indices.max()} != {len(vertices) - 1}"
# assert indices.min() == 0, f"min({indices}) != 0"
# assert np.unique(indices.flatten()).size == len(vertices)
assert len(tex_coord) == 0 or tex_coord.ndim == 2
assert len(tex_coord) == 0 or tex_coord.shape[1] == 2

View File

@@ -6,7 +6,7 @@ import sys
import time
from dataclasses import dataclass
from threading import Thread
from typing import Optional, Dict, Union
from typing import Optional, Dict, Union, Callable
import aiohttp_cors
from OCP.TopLoc import TopLoc_Location
@@ -16,7 +16,7 @@ from aiohttp_sse import sse_response
from build123d import Shape, Axis, Location, Vector
from dataclasses_json import dataclass_json
from yacv_server.cad import get_shape, grab_all_cad, image_to_gltf
from yacv_server.cad import get_shape, grab_all_cad, image_to_gltf, CADLike
from yacv_server.mylogger import logger
from yacv_server.pubsub import BufferedPubSub
from yacv_server.tessellate import _hashcode, tessellate
@@ -47,12 +47,12 @@ class UpdatesApiData:
class UpdatesApiFullData(UpdatesApiData):
obj: Optional[TopoDS_Shape]
obj: Optional[CADLike]
"""The OCCT object, if any (not serialized)"""
kwargs: Optional[Dict[str, any]]
"""The show_object options, if any (not serialized)"""
def __init__(self, name: str, hash: str, obj: Optional[TopoDS_Shape] = None,
def __init__(self, name: str, hash: str, obj: Optional[CADLike] = None,
kwargs: Optional[Dict[str, any]] = None):
self.name = name
self.hash = hash
@@ -126,21 +126,23 @@ class Server:
print('Cannot stop server because it is not running')
return
if os.getenv('YACV_STOP_EARLY', '') == '':
# Make sure we can hold the lock for more than 100ms (to avoid exiting too early)
logger.info('Stopping server (waiting for at least one frontend request first, cancel with CTRL+C)...')
try:
while not self.at_least_one_client.is_set():
time.sleep(0.01)
except KeyboardInterrupt:
pass
logger.info('Stopping server (waiting for no more frontend requests)...')
acquired = time.time()
while time.time() - acquired < 1.0:
if self.frontend_lock.locked():
acquired = time.time()
graceful_secs_connect = float(os.getenv('YACV_GRACEFUL_SECS_CONNECT', 12.0))
graceful_secs_request = float(os.getenv('YACV_GRACEFUL_SECS_REQUEST', 5.0))
# Make sure we can hold the lock for more than 100ms (to avoid exiting too early)
logger.info('Stopping server (waiting for at least one frontend request first, cancel with CTRL+C)...')
start = time.time()
try:
while not self.at_least_one_client.is_set() and time.time() - start < graceful_secs_connect:
time.sleep(0.01)
except KeyboardInterrupt:
pass
logger.info('Stopping server (waiting for no more frontend requests)...')
start = time.time()
while time.time() - start < graceful_secs_request:
if self.frontend_lock.locked():
start = time.time()
time.sleep(0.01)
# Stop the server in the background
self.loop.call_soon_threadsafe(lambda *a: self.do_shutdown.set())
@@ -190,7 +192,6 @@ class Server:
self.at_least_one_client.set()
async with sse_response(request) as resp:
logger.debug('Client connected: %s', request.remote)
resp.ping_interval = 0.1 # HACK: forces flushing of the buffer
# Send buffered events first, while keeping a lock
async with self.frontend_lock:
@@ -214,7 +215,7 @@ class Server:
obj_counter = 0
def _show_common(self, name: Optional[str], hash: str, start: float, obj: Optional[TopoDS_Shape] = None,
def _show_common(self, name: Optional[str], hash: str, start: float, obj: Optional[CADLike] = None,
kwargs=None):
name = name or f'object_{self.obj_counter}'
self.obj_counter += 1
@@ -230,7 +231,7 @@ class Server:
logger.info('show_object(%s, %s) took %.3f seconds', name, hash, time.time() - start)
return precomputed_info
def show(self, any_object: Union[bytes, TopoDS_Shape, any], name: Optional[str] = None, **kwargs):
def show(self, any_object: Union[bytes, CADLike, any], name: Optional[str] = None, **kwargs):
"""Publishes "any" object to the server"""
if isinstance(any_object, bytes):
self.show_gltf(any_object, name, **kwargs)
@@ -256,7 +257,7 @@ class Server:
# Publish it like any other GLTF object
self.show_gltf(gltf, name, **kwargs)
def show_cad(self, obj: Union[TopoDS_Shape, any], name: Optional[str] = None, **kwargs):
def show_cad(self, obj: Union[CADLike, any], name: Optional[str] = None, **kwargs):
"""Publishes a CAD object to the server"""
start = time.time()
@@ -338,21 +339,22 @@ class Server:
logger.debug('Building object %s... %s', name, event.obj)
_build_object()
# In either case return the elements of a subscription to the async generator
subscription = self.object_events[name].subscribe()
try:
return await anext(subscription)
finally:
await subscription.aclose()
# In either case return the elements of a subscription to the async generator
subscription = self.object_events[name].subscribe()
try:
return await anext(subscription)
finally:
await subscription.aclose()
def export_all(self, folder: str) -> None:
def export_all(self, folder: str, export_filter: Callable[[str, Optional[CADLike]], bool] = lambda name, obj: True):
"""Export all previously-shown objects to GLB files in the given folder"""
import asyncio
async def _export_all():
os.makedirs(folder, exist_ok=True)
for name in self.shown_object_names():
with open(os.path.join(folder, f'{name}.glb'), 'wb') as f:
f.write(await self.export(name))
if export_filter(name, self._shown_object(name).obj):
with open(os.path.join(folder, f'{name}.glb'), 'wb') as f:
f.write(await self.export(name))
asyncio.run(_export_all())

View File

@@ -13,9 +13,9 @@ from OCP.TopoDS import TopoDS_Face, TopoDS_Edge, TopoDS_Shape, TopoDS_Vertex
from build123d import Shape, Vertex, Face, Location
from pygltflib import GLTF2
from yacv_server.mylogger import logger
from yacv_server.cad import CADLike
from yacv_server.gltf import GLTFMgr
from yacv_server.mylogger import logger
def tessellate(

View File

@@ -805,10 +805,10 @@
resolved "https://registry.yarnpkg.com/@types/ndarray/-/ndarray-1.0.14.tgz#96b28c09a3587a76de380243f87bb7a2d63b4b23"
integrity sha512-oANmFZMnFQvb219SSBIhI1Ih/r4CvHDOzkWyJS/XRqkMrGH5/kaPSA1hQhdIBzouaE+5KpE/f5ylI9cujmckQg==
"@types/node@^20.11.24":
version "20.11.24"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.24.tgz#cc207511104694e84e9fb17f9a0c4c42d4517792"
integrity sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==
"@types/node@^20.11.25":
version "20.11.25"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.25.tgz#0f50d62f274e54dd7a49f7704cc16bfbcccaf49f"
integrity sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==
dependencies:
undici-types "~5.26.4"
@@ -851,26 +851,26 @@
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz#508d6a0f2440f86945835d903fcc0d95d1bb8a37"
integrity sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==
"@volar/language-core@2.1.1", "@volar/language-core@~2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@volar/language-core/-/language-core-2.1.1.tgz#ea7c2448ac5bdb2dd2ed202e5ff57929cb8ef191"
integrity sha512-oVbZcj97+5zlowkHMSJMt3aaAFuFyhXeXoOEHcqGECxFvw1TPCNnMM9vxhqNpoiNeWKHvggoq9WCk/HzJHtP8A==
"@volar/language-core@2.1.2", "@volar/language-core@~2.1.2":
version "2.1.2"
resolved "https://registry.yarnpkg.com/@volar/language-core/-/language-core-2.1.2.tgz#2053c0ee48a822d5418be2c192e51e580764b49f"
integrity sha512-5qsDp0Gf6fE09UWCeK7bkVn6NxMwC9OqFWQkMMkeej8h8XjyABPdRygC2RCrqDrfVdGijqlMQeXs6yRS+vfZYA==
dependencies:
"@volar/source-map" "2.1.1"
"@volar/source-map" "2.1.2"
"@volar/source-map@2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-2.1.1.tgz#9ca00177177417496a0364cea2f965445e19abb2"
integrity sha512-OOtxrEWB2eZ+tnCy5JwDkcCPGlN3+ioNNzkywXE9k4XA7p4cN36frR7QPAOksvd7RXKUGHzSjq6XrYnTPa4z4Q==
"@volar/source-map@2.1.2":
version "2.1.2"
resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-2.1.2.tgz#d270ff8ef5c814582f0efe08272c0fd6b9effb3b"
integrity sha512-yFJqsuLm1OaWrsz9E3yd3bJcYIlHqdZ8MbmIoZLrAzMYQDcoF26/INIhgziEXSdyHc8xd7rd/tJdSnUyh0gH4Q==
dependencies:
muggle-string "^0.4.0"
"@volar/typescript@~2.1.1":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@volar/typescript/-/typescript-2.1.1.tgz#b3dddaf39140cc0e00d67bad943496e2470a3882"
integrity sha512-5K41AWvFZCMMKZCx8bbFvbkyiKHr0s9k8P0M1FVXLX/9HYHzK5C9B8cX4uhATSehAytFIRnR4fTXVQtWp/Yzag==
"@volar/typescript@~2.1.2":
version "2.1.2"
resolved "https://registry.yarnpkg.com/@volar/typescript/-/typescript-2.1.2.tgz#61f838cf4410e328a7ba638fadc41bb814772508"
integrity sha512-lhTancZqamvaLvoz0u/uth8dpudENNt2LFZOWCw9JZiX14xRFhdhfzmphiCRb7am9E6qAJSbdS/gMt1utXAoHQ==
dependencies:
"@volar/language-core" "2.1.1"
"@volar/language-core" "2.1.2"
path-browserify "^1.0.1"
"@vue/babel-helper-vue-transform-on@1.2.1":
@@ -948,12 +948,12 @@
"@vue/compiler-dom" "3.4.21"
"@vue/shared" "3.4.21"
"@vue/language-core@2.0.5":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-2.0.5.tgz#bd3502604ea785f4171815005997988563f18469"
integrity sha512-knGXuQqhDSO7QJr8LFklsiWa23N2ikehkdVxtc9UKgnyqsnusughS2Tkg7VN8Hqed35X0B52Z+OGI5OrT/8uxQ==
"@vue/language-core@2.0.6":
version "2.0.6"
resolved "https://registry.yarnpkg.com/@vue/language-core/-/language-core-2.0.6.tgz#876f90622a3f801dce5cedcd6eae429d732152e2"
integrity sha512-UzqU12tzf9XLqRO3TiWPwRNpP4fyUzE6MAfOQWQNZ4jy6a30ARRUpmODDKq6O8C4goMc2AlPqTmjOHPjHkilSg==
dependencies:
"@volar/language-core" "~2.1.1"
"@volar/language-core" "~2.1.2"
"@vue/compiler-dom" "^3.4.0"
"@vue/shared" "^3.4.0"
computeds "^0.0.1"
@@ -2878,10 +2878,10 @@ tar@^6.1.11, tar@^6.1.2:
mkdirp "^1.0.3"
yallist "^4.0.0"
terser@^5.28.1:
version "5.28.1"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.28.1.tgz#bf00f7537fd3a798c352c2d67d67d65c915d1b28"
integrity sha512-wM+bZp54v/E9eRRGXb5ZFDvinrJIOaTapx3WUokyVGZu5ucVCK55zEgGd5Dl2fSr3jUo5sDiERErUWLY6QPFyA==
terser@^5.29.1:
version "5.29.1"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.29.1.tgz#44e58045b70c09792ba14bfb7b4e14ca8755b9fa"
integrity sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==
dependencies:
"@jridgewell/source-map" "^0.3.3"
acorn "^8.8.2"
@@ -2935,10 +2935,10 @@ tunnel-agent@^0.6.0:
dependencies:
safe-buffer "^5.0.1"
typescript@~5.3.0:
version "5.3.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
typescript@~5.4.2:
version "5.4.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.2.tgz#0ae9cebcfae970718474fe0da2c090cad6577372"
integrity sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==
undici-types@~5.26.4:
version "5.26.5"
@@ -3011,13 +3011,13 @@ vue-template-compiler@^2.7.14:
de-indent "^1.0.2"
he "^1.2.0"
vue-tsc@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-2.0.5.tgz#f491e24d74fcbf50cc3a71fce5ac2c99ee6335d9"
integrity sha512-e8WCgOVTrbmC04XPnI+IpaMTFYKaTm5s/MXFcvxO1l9kxzn+9FpGNVrBSlQE8VpTJaJg4kaBK1nj3NC20VJzjw==
vue-tsc@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-2.0.6.tgz#29cb195ffea63d66ec70b64eb4aadc6cd162bb12"
integrity sha512-kK50W4XqQL34vHRkxlRWLicrT6+F9xfgCgJ4KSmCHcytKzc1u3c94XXgI+CjmhOSxyw0krpExF7Obo7y4+0dVQ==
dependencies:
"@volar/typescript" "~2.1.1"
"@vue/language-core" "2.0.5"
"@volar/typescript" "~2.1.2"
"@vue/language-core" "2.0.6"
semver "^7.5.4"
vue@^3.4.21:
@@ -3031,10 +3031,10 @@ vue@^3.4.21:
"@vue/server-renderer" "3.4.21"
"@vue/shared" "3.4.21"
vuetify@^3.5.7:
version "3.5.7"
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-3.5.7.tgz#9dfa027a582aa7d2211c8019c33ef7cadd66c5c0"
integrity sha512-BFj/puY8odRwY50pRfE1gpawnxreY8PtPb/tDw3oumxSLXhoXw8q6YLA6QUvqZrYEzcYpojxZIYhNWUky2KN1w==
vuetify@^3.5.8:
version "3.5.8"
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-3.5.8.tgz#bc8f08dfd3314640e7b5d43b50138a26d650cbbf"
integrity sha512-8nGS+lKejZkev55HFwIfsRt+9fOqbeDQNmXxfmLKAlnUT8FtynVwbjAwHMtX/OQAQ3ZwRaR1ptqQQmx3OgxzbQ==
walk-up-path@^3.0.1:
version "3.0.1"