From d2276e49d385e7a0cb8768b8401e61a8a495e661 Mon Sep 17 00:00:00 2001 From: Quentin Frey <51170829+Limosine@users.noreply.github.com> Date: Sun, 15 Sep 2024 17:53:21 +0200 Subject: [PATCH] fixes #28; frontend, backend: await ws connection --- .../{frontend => }/.vscode/extensions.json | 0 packages/{frontend => }/.vscode/settings.json | 21 ++++- packages/backend/.vscode/settings.json | 26 ------- packages/backend/src/ws.ts | 4 + packages/common/.vscode/settings.json | 8 -- packages/common/api/common.ts | 24 ++++-- packages/frontend/package.json | 2 +- packages/frontend/src/lib/api/client.ts | 38 +++++---- .../frontend/src/lib/dialogs/Privacy.svelte | 5 +- .../src/lib/dialogs/PushRequest.svelte | 5 +- packages/frontend/src/lib/lib/UI.ts | 1 - packages/frontend/src/lib/lib/error.svelte.ts | 31 ++++++++ .../frontend/src/lib/lib/notifications.ts | 3 +- .../frontend/src/lib/lib/settings.svelte.ts | 57 ++++++++++++++ .../src/routes/[...path]/+layout.svelte | 78 ++++++++++++------- packages/frontend/yarn.lock | 72 ++++++++++------- 16 files changed, 252 insertions(+), 123 deletions(-) rename packages/{frontend => }/.vscode/extensions.json (100%) rename packages/{frontend => }/.vscode/settings.json (71%) delete mode 100644 packages/backend/.vscode/settings.json delete mode 100644 packages/common/.vscode/settings.json create mode 100644 packages/frontend/src/lib/lib/error.svelte.ts create mode 100644 packages/frontend/src/lib/lib/settings.svelte.ts diff --git a/packages/frontend/.vscode/extensions.json b/packages/.vscode/extensions.json similarity index 100% rename from packages/frontend/.vscode/extensions.json rename to packages/.vscode/extensions.json diff --git a/packages/frontend/.vscode/settings.json b/packages/.vscode/settings.json similarity index 71% rename from packages/frontend/.vscode/settings.json rename to packages/.vscode/settings.json index 59a64a9..d3c9292 100644 --- a/packages/frontend/.vscode/settings.json +++ b/packages/.vscode/settings.json @@ -1,9 +1,24 @@ { - "typescript.tsdk": "node_modules\\typescript\\lib", + "deno.enablePaths": ["./backend/", "./common/"], + "deno.enable": true, "cSpell.words": [ + "adminsdk", + "coturn", + "COTURN", + "dayjs", + "fileplay", "filetransfer", "Filetransfer", - "filetransfers" + "filetransfers", + "frey", + "GCMAPI", + "hono", + "jose", + "kysely", + "msgpackr", + "nixos", + "postgres", + "webpush" ], "sqltools.connections": [ { @@ -11,7 +26,7 @@ "server": "127.0.0.1", "port": 5432, "driver": "PostgreSQL", - "name": "FIleplay (Local)", + "name": "Fileplay (Local)", "database": "fileplay", "username": "fileplay", "password": "fileplay" diff --git a/packages/backend/.vscode/settings.json b/packages/backend/.vscode/settings.json deleted file mode 100644 index ef4afe5..0000000 --- a/packages/backend/.vscode/settings.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "deno.enablePaths": [ - "./", - "../common/" - ], - "deno.enable": true, - "cSpell.words": [ - "adminsdk", - "coturn", - "COTURN", - "dayjs", - "fileplay", - "filetransfer", - "Filetransfer", - "filetransfers", - "frey", - "GCMAPI", - "hono", - "jose", - "kysely", - "msgpackr", - "nixos", - "postgres", - "webpush" - ] -} \ No newline at end of file diff --git a/packages/backend/src/ws.ts b/packages/backend/src/ws.ts index 5836603..0eb57ee 100644 --- a/packages/backend/src/ws.ts +++ b/packages/backend/src/ws.ts @@ -101,12 +101,16 @@ export const onOpen = async (ws: WSContext, c: Context) => { (client.device === undefined || client.user === undefined) ) { console.log("INFO: Authentication failure"); + + sendMessage(client, { type: "status", data: "unauthorized" }); return client.close(1008, "Unauthorized"); } // Add to clients clients.add(client); + sendMessage(client, { type: "status", data: "authorized" }); + // Notify devices if (client.user !== undefined) deviceStateChanged(constants.db, client.user); }; diff --git a/packages/common/.vscode/settings.json b/packages/common/.vscode/settings.json deleted file mode 100644 index 18f6d87..0000000 --- a/packages/common/.vscode/settings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "cSpell.words": [ - "Dicebear", - "filetransfer", - "Filetransfer", - "webrtc" - ], -} \ No newline at end of file diff --git a/packages/common/api/common.ts b/packages/common/api/common.ts index f1618fa..b8e1144 100644 --- a/packages/common/api/common.ts +++ b/packages/common/api/common.ts @@ -12,6 +12,11 @@ function type(...t: [T, ...T[]]) { // Messages from server +const status = z.object({ + type: type("status"), + data: type("authorized", "unauthorized"), +}); + export const user = z.object({ type: type("user"), data: z.object({ @@ -320,6 +325,7 @@ const messageFromServerSchemaWithoutId = z.union([ closeConnection, codeRedeemed, error, + status, ]); export const messageFromServerSchema = messageFromServerSchemaWithoutId.and( @@ -328,11 +334,17 @@ export const messageFromServerSchema = messageFromServerSchemaWithoutId.and( }) ); -export type MessageFromServer = z.infer; +export type MessageFromServer = z.infer< + typeof messageFromServerSchemaWithoutId +>; export type ResponseMap = - T extends z.infer ? Promise["data"]> : - T extends z.infer ? Promise["data"]> : - T extends z.infer ? Promise["data"]> : - T extends z.infer ? Promise["data"]> : - undefined; + T extends z.infer + ? Promise["data"]> + : T extends z.infer + ? Promise["data"]> + : T extends z.infer + ? Promise["data"]> + : T extends z.infer + ? Promise["data"]> + : undefined; diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 3b39d58..4b06295 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -36,7 +36,7 @@ "pwa-asset-generator": "^6.3.1", "qrcode": "^1.5.3", "simple-peer": "^9.11.1", - "svelte": "^5.0.0-next.154", + "svelte": "^5.0.0-next.246", "svelte-check": "^3.8.0", "tslib": "^2.6.3", "typescript": "^5.4.5", diff --git a/packages/frontend/src/lib/api/client.ts b/packages/frontend/src/lib/api/client.ts index fe09a88..7ea233a 100644 --- a/packages/frontend/src/lib/api/client.ts +++ b/packages/frontend/src/lib/api/client.ts @@ -1,8 +1,8 @@ import { browser } from "$app/environment"; import { pack, unpack } from "msgpackr"; import { get, readable, writable } from "svelte/store"; -import type { MaybePromise } from "@sveltejs/kit"; +import { error } from "$lib/lib/error.svelte"; import { peer } from "$lib/lib/p2p"; import { closeDialog, @@ -12,7 +12,6 @@ import { dialogProperties, groupDevices, groups, - offline, user, userParams, } from "$lib/lib/UI"; @@ -85,6 +84,7 @@ class HTTPClient { } class WebSocketClient { + connected = writable(false); private socket: WebSocket; private messageId: number; private promises: ((value: any) => void)[]; @@ -98,6 +98,14 @@ class WebSocketClient { this.socket = this.connect(); } + private onOpen = () => { + if (!onGuestPage()) { + this.sendMessage({ type: "deleteTransfer" }); + this.sendMessage({ type: "getInfos" }); + } + this.sendBuffered(); + }; + private connect() { this.socket = new WebSocket( `${browser && location.protocol == "https:" ? "wss:" : "ws:"}//${location.host}/api/websocket?type=${onGuestPage() ? "guest" : "main"}`, @@ -105,14 +113,6 @@ class WebSocketClient { this.socket.binaryType = "arraybuffer"; - this.socket.addEventListener("open", () => { - if (!onGuestPage()) { - this.sendMessage({ type: "deleteTransfer" }); - this.sendMessage({ type: "getInfos" }); - } - this.sendBuffered(); - }); - this.socket.addEventListener("message", (event) => { let data; if (event.data instanceof ArrayBuffer) { @@ -132,18 +132,19 @@ class WebSocketClient { "WebSocket closed" + (event.reason ? ", reason: " + event.reason : "."), ); + if (get(this.connected)) this.connected.set(false); get(peer).closeConnections("websocket"); if (event.code !== 1008) { - if (get(offline) === true) { - const unsubscribe = offline.subscribe(async (offline) => { - if (!offline) { + if (get(error.error) !== false) { + const unsubscribe = error.error.subscribe(async (error) => { + if (error === false) { unsubscribe(); this.connect(); } }); } else setTimeout(() => this.connect(), 5000); - } else location.href = "/setup"; + } }); return this.socket; @@ -182,7 +183,14 @@ class WebSocketClient { } private handleData(message: MessageFromServer & { id: number }) { - if (message.type == "user") { + if (message.type == "status") { + if (message.data == "authorized" && !get(this.connected)) { + this.connected.set(true); + this.onOpen(); + } else if (message.data == "unauthorized") { + error.unauthorized(); + } + } else if (message.type == "user") { userParams.set({ display_name: message.data.display_name, avatar_seed: message.data.avatar_seed, diff --git a/packages/frontend/src/lib/dialogs/Privacy.svelte b/packages/frontend/src/lib/dialogs/Privacy.svelte index 3003be3..7cd3bb6 100644 --- a/packages/frontend/src/lib/dialogs/Privacy.svelte +++ b/packages/frontend/src/lib/dialogs/Privacy.svelte @@ -1,12 +1,13 @@

Enable notifications?

@@ -11,14 +12,14 @@ width < 840 ? "mobile" : "desktop", ); -export const offline = writable(false); // Navigation export const path = writable({ diff --git a/packages/frontend/src/lib/lib/error.svelte.ts b/packages/frontend/src/lib/lib/error.svelte.ts new file mode 100644 index 0000000..855764c --- /dev/null +++ b/packages/frontend/src/lib/lib/error.svelte.ts @@ -0,0 +1,31 @@ +import { writable } from "svelte/store"; + +class VisibleError { + overlay = $state<"" | "hidden">(""); + readonly error = writable(false); + + solved = () => { + this.error.set(false); + this.overlay = "hidden"; + }; + + offline = () => { + this.error.set({ + icon: "cloud_off", + text: "Offline, please connect to the internet.", + }); + this.overlay = ""; + }; + + unauthorized = () => { + this.error.set({ + icon: "warning", + text: "Unauthorized, forwarding to setup.", + }); + this.overlay = ""; + + setTimeout(() => (location.href = "/setup"), 2000); + }; +} + +export const error = new VisibleError(); diff --git a/packages/frontend/src/lib/lib/notifications.ts b/packages/frontend/src/lib/lib/notifications.ts index a6a3468..30e7fbe 100644 --- a/packages/frontend/src/lib/lib/notifications.ts +++ b/packages/frontend/src/lib/lib/notifications.ts @@ -2,6 +2,7 @@ import { writable } from "svelte/store"; import { PUBLIC_VAPID_KEY } from "$env/static/public"; import { apiClient } from "$lib/api/client"; +import { settings } from "$lib/lib/settings.svelte"; class Notifications { initialized: boolean; @@ -31,7 +32,7 @@ class Notifications { applicationServerKey: PUBLIC_VAPID_KEY, }); - localStorage.setItem("subscribedToPush", JSON.stringify(subscription)); + settings.set("subscribedToPush", JSON.stringify(subscription)); apiClient("ws").sendMessage({ type: "updateDevice", diff --git a/packages/frontend/src/lib/lib/settings.svelte.ts b/packages/frontend/src/lib/lib/settings.svelte.ts new file mode 100644 index 0000000..ed42a95 --- /dev/null +++ b/packages/frontend/src/lib/lib/settings.svelte.ts @@ -0,0 +1,57 @@ +import { openDB, type DBSchema, type IDBPDatabase } from "idb"; + +interface SettingsDB extends DBSchema { + settings: { + value: string; + key: string; + }; +} + +class Settings { + private database: () => IDBPDatabase; + settings = $state<{ [index: string]: string | undefined }>({}); + ready = $state(false); + + constructor() { + this.database = () => { + throw new Error("Database not initialized"); + }; + } + + init = async () => { + const db = await this.openDatabase(); + this.database = () => db; + + await this.getAll(); + this.ready = true; + }; + + private openDatabase = () => + openDB("settings-store", 1, { + upgrade(db) { + db.createObjectStore("settings"); + }, + }); + + private get = async (key: string) => this.database().get("settings", key); + + set = async (key: string, val: string) => { + await this.database().put("settings", val, key); + this.settings[key] = val; + }; + + clear = async () => this.database().clear("settings"); + + private keys = async () => this.database().getAllKeys("settings"); + + private getAll = async () => { + const keys = await this.keys(); + + for (const key of keys) { + const val = await this.get(key); + if (val !== undefined) this.settings[key] = val; + } + }; +} + +export const settings = new Settings(); diff --git a/packages/frontend/src/routes/[...path]/+layout.svelte b/packages/frontend/src/routes/[...path]/+layout.svelte index d48c66f..d9a7db9 100644 --- a/packages/frontend/src/routes/[...path]/+layout.svelte +++ b/packages/frontend/src/routes/[...path]/+layout.svelte @@ -3,6 +3,7 @@ import { page } from "$app/stores"; import { onMount, type Snippet } from "svelte"; import { quadOut } from "svelte/easing"; + import { get } from "svelte/store"; import { fade } from "svelte/transition"; import { pwaInfo } from "virtual:pwa-info"; import { useRegisterSW } from "virtual:pwa-register/svelte"; @@ -10,15 +11,17 @@ import ui from "beercss"; import * as materialSymbols from "beercss/dist/cdn/material-symbols-outlined.woff2"; + import { apiClient } from "$lib/api/client"; + import { error } from "$lib/lib/error.svelte"; import { closeDialog, getPath, largeDialog, - offline, openDialog, path, registration, } from "$lib/lib/UI"; + import { settings } from "$lib/lib/settings.svelte"; import logo from "$lib/assets/Fileplay.svg"; import Layout from "$lib/components/Layout.svelte"; @@ -32,33 +35,51 @@ } = $props(); let webManifest = $derived(pwaInfo?.webManifest?.linkTag); - let overlay = $state<"" | "hidden">(""); + const errorStore = error.error; - onMount(() => { + onMount(async () => { const open = () => { if ( - localStorage.getItem("subscribedToPush") === null && - localStorage.getItem("privacyAccepted") == "true" + settings.settings["subscribedToPush"] === undefined && + settings.settings["privacyAccepted"] == "true" ) openDialog({ mode: "request" }); }; if (browser) { - $offline = !navigator.onLine; - - if (localStorage.getItem("loggedIn") == "true") overlay = "hidden"; - - window.addEventListener("online", () => { - $offline = false; - overlay = "hidden"; - }); - window.addEventListener("offline", () => { - closeDialog(); - if ($largeDialog?.open) ui("#dialog-large"); - - $offline = true; - overlay = ""; - }); + await settings.init(); + if (!navigator.onLine) error.offline(); + + const continueMount = () => { + error.overlay = "hidden"; + + window.addEventListener("online", () => { + error.solved(); + }); + window.addEventListener("offline", () => { + closeDialog(); + if ($largeDialog?.open) ui("#dialog-large"); + + error.offline(); + }); + + if (settings.settings["privacyAccepted"] === undefined) + openDialog({ mode: "privacy" }); + }; + + if (localStorage.getItem("loggedIn") == "true") { + if (get(apiClient("ws").connected)) continueMount(); + else { + const unsubscribe = apiClient("ws").connected.subscribe( + async (connected) => { + if (connected) { + unsubscribe(); + continueMount(); + } + }, + ); + } + } } if (pwaInfo) { @@ -75,9 +96,6 @@ }, }); } - - if (localStorage.getItem("privacyAccepted") === null) - openDialog({ mode: "privacy" }); }); $effect(() => { @@ -97,7 +115,7 @@ /> -{#if !overlay} +{#if !error.overlay}
@@ -119,16 +137,16 @@ in:fade={{ duration: 200 }} out:fade={{ delay: 200, duration: 1000, easing: quadOut }} > - {#if $offline} - cloud_off -

Offline, please connect to the internet.

+ {#if $errorStore !== false} + {$errorStore.icon} +

{$errorStore.text}

{/if}
{/if} -
+
-{#if overlay} +{#if error.overlay} {#if $path.main == "send" || $path.main == "groups" || $path.main == "settings"} diff --git a/packages/frontend/yarn.lock b/packages/frontend/yarn.lock index 9469bbd..931decd 100644 --- a/packages/frontend/yarn.lock +++ b/packages/frontend/yarn.lock @@ -7,7 +7,7 @@ resolved "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@ampproject/remapping@^2.2.0", "@ampproject/remapping@^2.2.1": +"@ampproject/remapping@^2.2.0": version "2.2.1" resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz" integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== @@ -15,6 +15,14 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@ampproject/remapping@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + "@apideck/better-ajv-errors@^0.3.1": version "0.3.6" resolved "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz" @@ -1273,6 +1281,11 @@ resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@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== + "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": version "0.3.21" resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz" @@ -1726,6 +1739,11 @@ acorn@^8.11.3, acorn@^8.8.2, acorn@^8.9.0: resolved "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +acorn@^8.12.1: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + agent-base@6: version "6.0.2" resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" @@ -1795,12 +1813,10 @@ argparse@^2.0.1: resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -aria-query@^5.3.0: - version "5.3.0" - resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz" - integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== - dependencies: - dequal "^2.0.3" +aria-query@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.1.tgz#ebcb2c0d7fc43e68e4cb22f774d1209cb627ab42" + integrity sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g== array-buffer-byte-length@^1.0.0: version "1.0.0" @@ -1848,12 +1864,10 @@ available-typed-arrays@^1.0.5: resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== -axobject-query@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz" - integrity sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw== - dependencies: - dequal "^2.0.3" +axobject-query@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee" + integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== babel-plugin-polyfill-corejs2@^0.4.7: version "0.4.7" @@ -2289,11 +2303,6 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: has-property-descriptors "^1.0.0" object-keys "^1.1.1" -dequal@^2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz" - integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== - detect-indent@^6.1.0: version "6.1.0" resolved "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz" @@ -3625,6 +3634,13 @@ magic-string@^0.30.10: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" +magic-string@^0.30.11: + version "0.30.11" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.11.tgz#301a6f93b3e8c2cb13ac1a7a673492c0dfd12954" + integrity sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + magic-string@^0.30.5: version "0.30.5" resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz" @@ -4784,23 +4800,23 @@ svelte-preprocess@^5.1.3: sorcery "^0.11.0" strip-indent "^3.0.0" -svelte@^5.0.0-next.154: - version "5.0.0-next.154" - resolved "https://registry.yarnpkg.com/svelte/-/svelte-5.0.0-next.154.tgz#0e75cadf2058924eb7423dc90fa603abe7d4c1cc" - integrity sha512-fB7eVEqJ+79L/YBWm8CuKzoqc2+psgdRvlVeyi7y+18piElWLudOsfUNGStD06iFQ3SywyhWYf2HlzXxb4wXVg== +svelte@^5.0.0-next.246: + version "5.0.0-next.246" + resolved "https://registry.yarnpkg.com/svelte/-/svelte-5.0.0-next.246.tgz#99659940b41b6a300b4c7d668d4d1e427337ef8c" + integrity sha512-FRfq6W17mOHiSbY9nen6/skCV7AHQJdB9yaS9DA4x4mKXR/RIGMDLlxxU3jhQsMiLoqmUFHXJc6Rqe1o6HWlow== dependencies: - "@ampproject/remapping" "^2.2.1" - "@jridgewell/sourcemap-codec" "^1.4.15" + "@ampproject/remapping" "^2.3.0" + "@jridgewell/sourcemap-codec" "^1.5.0" "@types/estree" "^1.0.5" - acorn "^8.11.3" + acorn "^8.12.1" acorn-typescript "^1.4.13" - aria-query "^5.3.0" - axobject-query "^4.0.0" + aria-query "^5.3.1" + axobject-query "^4.1.0" esm-env "^1.0.0" esrap "^1.2.2" is-reference "^3.0.2" locate-character "^3.0.0" - magic-string "^0.30.5" + magic-string "^0.30.11" zimmerframe "^1.1.2" tar-fs@2.1.1: