From 11b57c226b1154a0ced0511d209ddf6059f30bcd Mon Sep 17 00:00:00 2001 From: Nova Date: Sun, 14 Jun 2026 19:46:32 -0600 Subject: [PATCH 1/6] web: write an error handler, install sdk, remove query thingy --- web/package.json | 7 +------ web/pnpm-lock.yaml | 24 ++++++++++++++---------- web/pnpm-workspace.yaml | 6 ++++++ web/utils/api.ts | 30 +++++------------------------- 4 files changed, 26 insertions(+), 41 deletions(-) diff --git a/web/package.json b/web/package.json index 70da62b..35f3364 100644 --- a/web/package.json +++ b/web/package.json @@ -9,6 +9,7 @@ "lint": "eslint" }, "dependencies": { + "@folderharbor/sdk": "^1.1.1", "@fortawesome/fontawesome-svg-core": "^7.2.0", "@fortawesome/free-brands-svg-icons": "^7.2.0", "@fortawesome/free-regular-svg-icons": "^7.2.0", @@ -31,11 +32,5 @@ "eslint-config-next": "16.2.6", "tailwindcss": "^4", "typescript": "^5" - }, - "pnpm": { - "overrides": { - "@types/react": "19.2.14", - "@types/react-dom": "19.2.3" - } } } diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 7b8b3ab..c2d5ca6 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -4,14 +4,13 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -overrides: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3 - importers: .: dependencies: + '@folderharbor/sdk': + specifier: ^1.1.1 + version: 1.1.1 '@fortawesome/fontawesome-svg-core': specifier: ^7.2.0 version: 7.2.0 @@ -194,6 +193,9 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@folderharbor/sdk@1.1.1': + resolution: {integrity: sha512-ObOAwaqmJaBIAxAMnx82eaK1h2wNWPGwXin9kqvFRn6Mnvq3XbdY+y38GeKnJniIeI7aTB3TjPFrVL4DLD4aRg==} + '@fortawesome/fontawesome-common-types@7.2.0': resolution: {integrity: sha512-IpR0bER9FY25p+e7BmFH25MZKEwFHTfRAfhOyJubgiDnoJNsSvJ7nigLraHtp4VOG/cy8D7uiV0dLkHOne5Fhw==} engines: {node: '>=6'} @@ -605,7 +607,7 @@ packages: '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: - '@types/react': 19.2.14 + '@types/react': ^19.2.0 '@types/react@19.2.14': resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} @@ -2202,6 +2204,8 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 + '@folderharbor/sdk@1.1.1': {} + '@fortawesome/fontawesome-common-types@7.2.0': {} '@fortawesome/fontawesome-svg-core@7.2.0': @@ -3011,7 +3015,7 @@ snapshots: '@next/eslint-plugin-next': 16.2.6 eslint: 9.39.4(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)) eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.4(jiti@2.6.1)) eslint-plugin-react: 7.37.5(eslint@9.39.4(jiti@2.6.1)) @@ -3034,7 +3038,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.3 @@ -3049,14 +3053,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) eslint: 9.39.4(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.6.1)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)) transitivePeerDependencies: - supports-color @@ -3071,7 +3075,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.39.4(jiti@2.6.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 diff --git a/web/pnpm-workspace.yaml b/web/pnpm-workspace.yaml index 581a9d5..a62c352 100644 --- a/web/pnpm-workspace.yaml +++ b/web/pnpm-workspace.yaml @@ -1,3 +1,9 @@ +allowBuilds: + sharp: true + unrs-resolver: true ignoredBuiltDependencies: - sharp - unrs-resolver +minimumReleaseAgeExclude: + - '@folderharbor/sdk@1.1.0' + - '@folderharbor/sdk@1.1.1' diff --git a/web/utils/api.ts b/web/utils/api.ts index e8754b3..6cc44e0 100644 --- a/web/utils/api.ts +++ b/web/utils/api.ts @@ -1,26 +1,6 @@ -import { Session } from "@/folderharborweb"; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export default async function query(session: Session, path: string, init?: RequestInit): Promise<{ error: string } | { redirect: string } |{ body: any }> { - let body; - const url = new URL(session.server); - url.pathname += path.split("?")[0]; - if (path.split("?").length >= 2) url.search += path.split("?")[1]; - const headers = new Headers(); - headers.append("Content-Type", "application/json"); - headers.append("Authorization", `Bearer ${session.token}`); - try { - const res = await fetch(url.toString(), { ...init, headers }); - if (res.status !== 204) body = await res.json(); - } catch (err) { return { error: `Error: ${err}` } } - if (body && "error" in body) { - switch (body.error) { - case "locked": - case "invalid": - case "expired": - return { redirect: `/fatal/${body.error}` } - default: - return { error: `Error (${body.error}): ${body.message}` } - } - } - return { body }; +import { FHAuthError, FHPermissionError, FHRequestError } from "@folderharbor/sdk"; +export async function handleErrors(error: FHRequestError | FHAuthError | FHPermissionError): Promise<{ error: string } | { redirect: string }> { + if (error instanceof FHAuthError) return { redirect: `/fatal/${error.code}` } + if (error instanceof FHPermissionError || error instanceof FHRequestError) return { error: `Error${error.code ? ` (${error.code})` : ""}: ${error.message}` } + return { error: `Error: ${error}` } } \ No newline at end of file From a33623f591901bcadda4c30481bb6d77d03538d3 Mon Sep 17 00:00:00 2001 From: Nova Date: Sun, 14 Jun 2026 20:36:15 -0600 Subject: [PATCH 2/6] web: start implementing more sdk methods --- web/app/auth/login.form.tsx | 40 +- web/app/header.module.tsx | 16 +- web/app/home/home.module.tsx | 26 +- web/app/refresher.module.tsx | 10 +- web/app/selector.module.tsx | 12 +- web/package.json | 2 +- web/pnpm-lock.yaml | 1359 ++++++++++++++++++---------------- web/pnpm-workspace.yaml | 3 +- web/utils/api.ts | 8 +- 9 files changed, 760 insertions(+), 716 deletions(-) diff --git a/web/app/auth/login.form.tsx b/web/app/auth/login.form.tsx index c82205f..1648a13 100644 --- a/web/app/auth/login.form.tsx +++ b/web/app/auth/login.form.tsx @@ -1,6 +1,8 @@ "use client" import { ClientConfig } from "@/folderharborweb"; +import { handleError } from "@/utils/api"; import { db } from "@/utils/db"; +import { FolderHarbor } from "@folderharbor/sdk"; import { faArrowRight, faPencil } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useRouter } from "next/navigation"; @@ -15,21 +17,16 @@ export default function LoginForm({ defaultURL }: { defaultURL: string | undefin const [clientConfig, setClientConfig] = useState(); async function handleSubmit(e: React.SubmitEvent) { e.preventDefault(); - let body; - const url = new URL(server); - url.pathname += "auth"; + let authRes; try { - const res = await fetch(url.toString(), { method: "POST", body: JSON.stringify({ username, password }), headers: { "Content-Type": "application/json" } }); - body = await res.json(); - } catch (err) { - alert(`Error logging you in: ${err}`); + authRes = await (new FolderHarbor({ server })).auth.login({ username, password }); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) router.push(errBody.redirect); return; } - if (body.error) { - alert(`Error logging you in: ${body.message} (${body.error})`); - return; - } - const session = await db.sessions.add({ server: new URL(server).toString(), token: body.token, username: username, permissions: body.permissions || [] }); + const session = await db.sessions.add({ server: new URL(server).toString(), token: authRes.token, username: username, permissions: authRes.permissions || [] }); if (session) localStorage.setItem("activeSession", session.toString()); if (await db.sessions.count() === 1) { router.push("/home"); @@ -38,21 +35,16 @@ export default function LoginForm({ defaultURL }: { defaultURL: string | undefin router.push("/"); } async function register() { - let body; - const url = new URL(server); - url.pathname += "auth/register"; + let res; try { - const res = await fetch(url.toString(), { method: "POST", body: JSON.stringify({ username, password }), headers: { "Content-Type": "application/json" } }); - body = await res.json(); - } catch (err) { - alert(`Error registering you: ${err}`); - return; - } - if (body.error) { - alert(`Error registering you: ${body.message} (${body.error})`); + res = await (new FolderHarbor({ server })).auth.register({ username, password }); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) router.push(errBody.redirect); return; } - const session = await db.sessions.add({ server: new URL(server).toString(), token: body.token, username: username, permissions: body.permissions || [] }); + const session = await db.sessions.add({ server: new URL(server).toString(), token: res.token, username: username, permissions: res.permissions || [] }); if (session) localStorage.setItem("activeSession", session.toString()); if (await db.sessions.count() === 1) { router.push("/home"); diff --git a/web/app/header.module.tsx b/web/app/header.module.tsx index f095716..68e836a 100644 --- a/web/app/header.module.tsx +++ b/web/app/header.module.tsx @@ -7,8 +7,8 @@ import { ReactNode, useEffect, useState } from "react"; import Image from "next/image"; import logo from "@/public/logo.webp"; import Link from "next/link"; -import query from "@/utils/api"; import { usePathname, useRouter } from "next/navigation"; +import { getClient, handleError } from "@/utils/api"; export default function Header({ children }: { children?: ReactNode }) { const router = useRouter(); @@ -22,14 +22,12 @@ export default function Header({ children }: { children?: ReactNode }) { async function signOut() { const tokenCheck = confirm("Do you want to invalidate this session's token? This will disconnect any clients you logged into with this token."); if (tokenCheck) { - const res = await query(session!, "auth", { method: "DELETE" }); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { - window.location.href = res.redirect; - return; + try { + await getClient(session!).auth.logout(); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) router.push(errBody.redirect); } } await db.sessions.delete(session!.webID); diff --git a/web/app/home/home.module.tsx b/web/app/home/home.module.tsx index 3c2703d..c93e846 100644 --- a/web/app/home/home.module.tsx +++ b/web/app/home/home.module.tsx @@ -1,6 +1,6 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; import { Source_Code_Pro } from "next/font/google"; import { useEffect, useState } from "react"; @@ -15,19 +15,21 @@ export default function Home() { loadSession(); }, []); useEffect(() => { - if (!session) return; - query(session, "protocols").then((res) => { - if ("error" in res) { - alert(res.error); + async function load() { + if (!session) return; + let protocols; + try { + protocols = await getClient(session).protocols(); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; return; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - setWebdavURL(res.body.webdav); - setftpURL(res.body.ftp); - }); + setWebdavURL(protocols.webdav); + setftpURL(protocols.ftp); + } + load(); }, [session]); return (
diff --git a/web/app/refresher.module.tsx b/web/app/refresher.module.tsx index b494be1..e385986 100644 --- a/web/app/refresher.module.tsx +++ b/web/app/refresher.module.tsx @@ -1,6 +1,6 @@ "use client" -import query from "@/utils/api"; import { db } from "@/utils/db"; +import { FolderHarbor } from "@folderharbor/sdk"; import { useEffect } from "react"; export default function RefreshSession() { @@ -9,9 +9,11 @@ export default function RefreshSession() { if (localStorage.getItem("activeSession")) { const session = await db.sessions.get(parseInt(localStorage.getItem("activeSession")!)); if (!session) return; - const res = await query(session, "me"); - if ("error" in res || "redirect" in res) return; - db.sessions.update(parseInt(localStorage.getItem("activeSession")!), { permissions: res.body.permissions || [], username: res.body.username }); + let res; + try { + res = await (new FolderHarbor({ server: session.server, token: session.token })).me.info(); + } catch { return; } + db.sessions.update(parseInt(localStorage.getItem("activeSession")!), { permissions: res.permissions || [], username: res.username }); } } refreshSession(); diff --git a/web/app/selector.module.tsx b/web/app/selector.module.tsx index bcb1de4..88ce823 100644 --- a/web/app/selector.module.tsx +++ b/web/app/selector.module.tsx @@ -1,6 +1,6 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; import { faServer, faTrash, faUserPlus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -14,9 +14,13 @@ export default function AccountSelector() { async function logOut(session: Session) { const tokenCheck = confirm("Do you want to invalidate this session's token? This will disconnect any clients you logged into with this token."); if (tokenCheck) { - const delReq = await query(session, "auth", { method: "DELETE" }); - if ("error" in delReq) alert(delReq.error); - if ("redirect" in delReq) router.push(delReq.redirect); + try { + await getClient(session).auth.logout(); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) router.push(errBody.redirect); + } } await db.sessions.delete(session.webID); localStorage.removeItem("activeSession"); diff --git a/web/package.json b/web/package.json index 35f3364..23adfb9 100644 --- a/web/package.json +++ b/web/package.json @@ -9,7 +9,7 @@ "lint": "eslint" }, "dependencies": { - "@folderharbor/sdk": "^1.1.1", + "@folderharbor/sdk": "^1.1.2", "@fortawesome/fontawesome-svg-core": "^7.2.0", "@fortawesome/free-brands-svg-icons": "^7.2.0", "@fortawesome/free-regular-svg-icons": "^7.2.0", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index c2d5ca6..31671ba 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@folderharbor/sdk': - specifier: ^1.1.1 - version: 1.1.1 + specifier: ^1.1.2 + version: 1.1.2 '@fortawesome/fontawesome-svg-core': specifier: ^7.2.0 version: 7.2.0 @@ -25,19 +25,19 @@ importers: version: 7.2.0 '@fortawesome/react-fontawesome': specifier: ^3.3.0 - version: 3.3.0(@fortawesome/fontawesome-svg-core@7.2.0)(react@19.2.6) + version: 3.3.1(@fortawesome/fontawesome-svg-core@7.2.0)(react@19.2.6) dexie: specifier: ^4.4.2 - version: 4.4.2 + version: 4.4.3 dexie-react-hooks: specifier: ^4.4.0 - version: 4.4.0(dexie@4.4.2)(react@19.2.6) + version: 4.4.0(dexie@4.4.3)(react@19.2.6) lodash-es: specifier: ^4.18.1 version: 4.18.1 next: specifier: 16.2.6 - version: 16.2.6(@babel/core@7.29.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + version: 16.2.6(@babel/core@7.29.7)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) react: specifier: 19.2.6 version: 19.2.6 @@ -47,13 +47,13 @@ importers: devDependencies: '@tailwindcss/postcss': specifier: ^4 - version: 4.2.2 + version: 4.3.1 '@types/lodash-es': specifier: ^4.17.12 version: 4.17.12 '@types/node': specifier: ^20 - version: 20.19.37 + version: 20.19.43 '@types/react': specifier: 19.2.14 version: 19.2.14 @@ -62,13 +62,13 @@ importers: version: 19.2.3(@types/react@19.2.14) eslint: specifier: ^9 - version: 9.39.4(jiti@2.6.1) + version: 9.39.4(jiti@2.7.0) eslint-config-next: specifier: 16.2.6 - version: 16.2.6(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + version: 16.2.6(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) tailwindcss: specifier: ^4 - version: 4.2.2 + version: 4.3.1 typescript: specifier: ^5 version: 5.9.3 @@ -79,81 +79,84 @@ packages: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} - '@babel/code-frame@7.29.0': - resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.29.0': - resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} engines: {node: '>=6.9.0'} - '@babel/core@7.29.0': - resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.29.1': - resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + '@babel/generator@7.29.7': + resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.28.6': - resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} engines: {node: '>=6.9.0'} - '@babel/helper-globals@7.28.0': - resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.28.6': - resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.28.6': - resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.27.1': - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.29.2': - resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} + '@babel/helpers@7.29.7': + resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} engines: {node: '>=6.9.0'} - '@babel/parser@7.29.2': - resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + '@babel/parser@7.29.7': + resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/template@7.28.6': - resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.29.0': - resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + '@babel/traverse@7.29.7': + resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} engines: {node: '>=6.9.0'} - '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + '@babel/types@7.29.7': + resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} engines: {node: '>=6.9.0'} - '@emnapi/core@1.9.1': - resolution: {integrity: sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==} + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} '@emnapi/runtime@1.10.0': resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} - '@emnapi/wasi-threads@1.2.0': - resolution: {integrity: sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==} + '@emnapi/runtime@1.11.1': + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} '@eslint-community/eslint-utils@4.9.1': resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} @@ -193,8 +196,8 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@folderharbor/sdk@1.1.1': - resolution: {integrity: sha512-ObOAwaqmJaBIAxAMnx82eaK1h2wNWPGwXin9kqvFRn6Mnvq3XbdY+y38GeKnJniIeI7aTB3TjPFrVL4DLD4aRg==} + '@folderharbor/sdk@1.1.2': + resolution: {integrity: sha512-LiK7RoGOf74MAOmGAzkaLUakQ0Vpco9tcvxT5GIGRF1ojl+gQc69fc6mnJ7E+zaDJMygSJeVI58U98eMFg3a3g==} '@fortawesome/fontawesome-common-types@7.2.0': resolution: {integrity: sha512-IpR0bER9FY25p+e7BmFH25MZKEwFHTfRAfhOyJubgiDnoJNsSvJ7nigLraHtp4VOG/cy8D7uiV0dLkHOne5Fhw==} @@ -216,19 +219,23 @@ packages: resolution: {integrity: sha512-YTVITFGN0/24PxzXrwqCgnyd7njDuzp5ZvaCx5nq/jg55kUYd94Nj8UTchBdBofi/L0nwRfjGOg0E41d2u9T1w==} engines: {node: '>=6'} - '@fortawesome/react-fontawesome@3.3.0': - resolution: {integrity: sha512-EHmHeTf8WgO29sdY3iX/7ekE3gNUdlc2RW6mm/FzELlHFKfTrA9S4MlyquRR+RRCRCn8+jXfLFpLGB2l7wCWyw==} + '@fortawesome/react-fontawesome@3.3.1': + resolution: {integrity: sha512-wGnAPhfzivDwBWYmEG8MSrEXPruoiMMo48NnsRkj1NZkoaawgOijPNAiSHKMYEoCsqTBSgLTzL6EqTTWGaUR4w==} engines: {node: '>=20'} peerDependencies: '@fortawesome/fontawesome-svg-core': ~6 || ~7 react: ^18.0.0 || ^19.0.0 - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} engines: {node: '>=18.18.0'} - '@humanfs/node@0.16.7': - resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} engines: {node: '>=18.18.0'} '@humanwhocodes/module-importer@1.0.1': @@ -408,8 +415,11 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@napi-rs/wasm-runtime@0.2.12': - resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + '@napi-rs/wasm-runtime@1.1.5': + resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 '@next/env@16.2.6': resolution: {integrity: sha512-gd8HoHN4ufj73WmR3JmVolrpJR47ILK6LouP5xElPglaVxir6e1a7VzvTvDWkOoPXT9rkkTzyCxBu4yeZfZwcw==} @@ -491,69 +501,69 @@ packages: '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - '@tailwindcss/node@4.2.2': - resolution: {integrity: sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==} + '@tailwindcss/node@4.3.1': + resolution: {integrity: sha512-6NDaqRoAMSXD1mr/RXu0HBvNE9a2n5tHPsxu9XHLws8o4Twes5rBM2205SUUiJ9goAtadrN6xTGX0UDEwp/N4A==} - '@tailwindcss/oxide-android-arm64@4.2.2': - resolution: {integrity: sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==} + '@tailwindcss/oxide-android-arm64@4.3.1': + resolution: {integrity: sha512-SVlyf61g374l5cHyg8x9kf5xmLcOaxvOTsbsqDnSsDJaKOEFZ7GCvi84VAVGpxojYOs1+3K6M0UjXfqPU8vmOQ==} engines: {node: '>= 20'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.2.2': - resolution: {integrity: sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==} + '@tailwindcss/oxide-darwin-arm64@4.3.1': + resolution: {integrity: sha512-hVnWLwv+e/l7c4WKyVtHVrIPvYdqWHjRB3MDIqARynzFtnQg85kmQEFCbV9Ja0VVx4xXTIiDWY60Y7iz/iNoDA==} engines: {node: '>= 20'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.2.2': - resolution: {integrity: sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==} + '@tailwindcss/oxide-darwin-x64@4.3.1': + resolution: {integrity: sha512-Cf7abu0WVgbhU7ANgPUnSAvm7nCvMweusHb8FnaHlLfv/Caq4GYaEZg7ZImzzmjx4lIAfuS8q+eLIS7A7IzxIg==} engines: {node: '>= 20'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.2.2': - resolution: {integrity: sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==} + '@tailwindcss/oxide-freebsd-x64@4.3.1': + resolution: {integrity: sha512-ZZqzX2Y+GXtXXfqSfpJhDm60OoZfvLHLCgm+J7NVqgHHJjG/m9ugZI77RwTsVd4fnBJuCFP6Ae6kTJb71UdS8g==} engines: {node: '>= 20'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': - resolution: {integrity: sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.1': + resolution: {integrity: sha512-/Ah/xik0LaMYfv9DZ0S/t4pBlBNYOcqtRwusjgovHkvT8ixueWCLyJjsaF5kQIckjb4IT8Q6K6p/iPmZMixYgg==} engines: {node: '>= 20'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': - resolution: {integrity: sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==} + '@tailwindcss/oxide-linux-arm64-gnu@4.3.1': + resolution: {integrity: sha512-gqdFoVJlw444GvpnheZLHmvTzSxI/cOUUh2KSNejQjTcYkW062SVD+En0rUgD+QV91bz1XGIGtt1HJd48xUGbQ==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-arm64-musl@4.2.2': - resolution: {integrity: sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==} + '@tailwindcss/oxide-linux-arm64-musl@4.3.1': + resolution: {integrity: sha512-Bwv9KwOvE0VKa86xPFif9b9c3Y1NxOV1P0gLti/IYaWEsQYZXDlxfGEtA8mdDZ7SG3wyNXAWYT5SIn3giL57oA==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [musl] - '@tailwindcss/oxide-linux-x64-gnu@4.2.2': - resolution: {integrity: sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==} + '@tailwindcss/oxide-linux-x64-gnu@4.3.1': + resolution: {integrity: sha512-Ymi8O8T15HYQdOUWUtTI6ldN0neHP85FC+Qz32xTcZ7iJXtem/x8ITev0o1e9e5rkqj4lONZfTRLvkmin1+tKg==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-x64-musl@4.2.2': - resolution: {integrity: sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==} + '@tailwindcss/oxide-linux-x64-musl@4.3.1': + resolution: {integrity: sha512-M+P/91qJ6uILLw4k2G93GMDRAXj61SMvFQYt39AqvUqYgExXpLL5aepfns7sj4HiAQeolirQF9E0lzRvdf4zPQ==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [musl] - '@tailwindcss/oxide-wasm32-wasi@4.2.2': - resolution: {integrity: sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==} + '@tailwindcss/oxide-wasm32-wasi@4.3.1': + resolution: {integrity: sha512-zsM8uOeqvVGHsAXsJxsT28ttosFahLJKCLOTUBqRAtKnVgGSRitds9T432QiT8b77Yga7JIBkulIRRlJPtYhRA==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -564,30 +574,30 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': - resolution: {integrity: sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==} + '@tailwindcss/oxide-win32-arm64-msvc@4.3.1': + resolution: {integrity: sha512-aiNvSq9BsVk8V513lDKlrCFAgf8qBMPZTpgEhInL+NwQqs97mYmupVMrPrgBBSL8Pv/0zXu9MrMF9rMun1ZeNg==} engines: {node: '>= 20'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.2.2': - resolution: {integrity: sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==} + '@tailwindcss/oxide-win32-x64-msvc@4.3.1': + resolution: {integrity: sha512-xDEyu1rg290472FEGaKHnzyDyh5QH+AlWvsU5hMoMtPpzmKlRI0jaYKCgSHDYtaQWZOYbMaduSyCwFwY4n1HmA==} engines: {node: '>= 20'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.2.2': - resolution: {integrity: sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==} + '@tailwindcss/oxide@4.3.1': + resolution: {integrity: sha512-yVPyo8RNkabVr3O2EhHEE0Rewu7YKzc1DhIqfL46LKveFrmu9XbDazNOJY7/GRuvw1h6u3utWnR29H/p5JPlgA==} engines: {node: '>= 20'} - '@tailwindcss/postcss@4.2.2': - resolution: {integrity: sha512-n4goKQbW8RVXIbNKRB/45LzyUqN451deQK0nzIeauVEqjlI49slUlgKYJM2QyUzap/PcpnS7kzSUmPb1sCRvYQ==} + '@tailwindcss/postcss@4.3.1': + resolution: {integrity: sha512-dNJuNbdEJT/SWRuXTYP1WSamelsz3ztkUsdtWQPjrexysrTpaEPM40P/71knXiXLYEojqPOEGitVLLpPMS5T6A==} - '@tybys/wasm-util@0.10.1': - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@tybys/wasm-util@0.10.2': + resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -601,8 +611,8 @@ packages: '@types/lodash@4.17.24': resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==} - '@types/node@20.19.37': - resolution: {integrity: sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==} + '@types/node@20.19.43': + resolution: {integrity: sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==} '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} @@ -612,165 +622,182 @@ packages: '@types/react@19.2.14': resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} - '@typescript-eslint/eslint-plugin@8.57.2': - resolution: {integrity: sha512-NZZgp0Fm2IkD+La5PR81sd+g+8oS6JwJje+aRWsDocxHkjyRw0J5L5ZTlN3LI1LlOcGL7ph3eaIUmTXMIjLk0w==} + '@typescript-eslint/eslint-plugin@8.61.0': + resolution: {integrity: sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.57.2 + '@typescript-eslint/parser': ^8.61.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.57.2': - resolution: {integrity: sha512-30ScMRHIAD33JJQkgfGW1t8CURZtjc2JpTrq5n2HFhOefbAhb7ucc7xJwdWcrEtqUIYJ73Nybpsggii6GtAHjA==} + '@typescript-eslint/parser@8.61.0': + resolution: {integrity: sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.57.2': - resolution: {integrity: sha512-FuH0wipFywXRTHf+bTTjNyuNQQsQC3qh/dYzaM4I4W0jrCqjCVuUh99+xd9KamUfmCGPvbO8NDngo/vsnNVqgw==} + '@typescript-eslint/project-service@8.61.0': + resolution: {integrity: sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.57.2': - resolution: {integrity: sha512-snZKH+W4WbWkrBqj4gUNRIGb/jipDW3qMqVJ4C9rzdFc+wLwruxk+2a5D+uoFcKPAqyqEnSb4l2ULuZf95eSkw==} + '@typescript-eslint/scope-manager@8.61.0': + resolution: {integrity: sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.57.2': - resolution: {integrity: sha512-3Lm5DSM+DCowsUOJC+YqHHnKEfFh5CoGkj5Z31NQSNF4l5wdOwqGn99wmwN/LImhfY3KJnmordBq/4+VDe2eKw==} + '@typescript-eslint/tsconfig-utils@8.61.0': + resolution: {integrity: sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.57.2': - resolution: {integrity: sha512-Co6ZCShm6kIbAM/s+oYVpKFfW7LBc6FXoPXjTRQ449PPNBY8U0KZXuevz5IFuuUj2H9ss40atTaf9dlGLzbWZg==} + '@typescript-eslint/type-utils@8.61.0': + resolution: {integrity: sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.57.2': - resolution: {integrity: sha512-/iZM6FnM4tnx9csuTxspMW4BOSegshwX5oBDznJ7S4WggL7Vczz5d2W11ecc4vRrQMQHXRSxzrCsyG5EsPPTbA==} + '@typescript-eslint/types@8.61.0': + resolution: {integrity: sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.57.2': - resolution: {integrity: sha512-2MKM+I6g8tJxfSmFKOnHv2t8Sk3T6rF20A1Puk0svLK+uVapDZB/4pfAeB7nE83uAZrU6OxW+HmOd5wHVdXwXA==} + '@typescript-eslint/typescript-estree@8.61.0': + resolution: {integrity: sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.57.2': - resolution: {integrity: sha512-krRIbvPK1ju1WBKIefiX+bngPs+odIQUtR7kymzPfo1POVw3jlF+nLkmexdSSd4UCbDcQn+wMBATOOmpBbqgKg==} + '@typescript-eslint/utils@8.61.0': + resolution: {integrity: sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.57.2': - resolution: {integrity: sha512-zhahknjobV2FiD6Ee9iLbS7OV9zi10rG26odsQdfBO/hjSzUQbkIYgda+iNKK1zNiW2ey+Lf8MU5btN17V3dUw==} + '@typescript-eslint/visitor-keys@8.61.0': + resolution: {integrity: sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@unrs/resolver-binding-android-arm-eabi@1.11.1': - resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} + '@unrs/resolver-binding-android-arm-eabi@1.12.2': + resolution: {integrity: sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==} cpu: [arm] os: [android] - '@unrs/resolver-binding-android-arm64@1.11.1': - resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} + '@unrs/resolver-binding-android-arm64@1.12.2': + resolution: {integrity: sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==} cpu: [arm64] os: [android] - '@unrs/resolver-binding-darwin-arm64@1.11.1': - resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} + '@unrs/resolver-binding-darwin-arm64@1.12.2': + resolution: {integrity: sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==} cpu: [arm64] os: [darwin] - '@unrs/resolver-binding-darwin-x64@1.11.1': - resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} + '@unrs/resolver-binding-darwin-x64@1.12.2': + resolution: {integrity: sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==} cpu: [x64] os: [darwin] - '@unrs/resolver-binding-freebsd-x64@1.11.1': - resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} + '@unrs/resolver-binding-freebsd-x64@1.12.2': + resolution: {integrity: sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==} cpu: [x64] os: [freebsd] - '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': - resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} + '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2': + resolution: {integrity: sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==} cpu: [arm] os: [linux] - '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': - resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} + '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2': + resolution: {integrity: sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==} cpu: [arm] os: [linux] - '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': - resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} + '@unrs/resolver-binding-linux-arm64-gnu@1.12.2': + resolution: {integrity: sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==} cpu: [arm64] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-arm64-musl@1.11.1': - resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} + '@unrs/resolver-binding-linux-arm64-musl@1.12.2': + resolution: {integrity: sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==} cpu: [arm64] os: [linux] libc: [musl] - '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': - resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} + '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': + resolution: {integrity: sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-loong64-musl@1.12.2': + resolution: {integrity: sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': + resolution: {integrity: sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==} cpu: [ppc64] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': - resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} + '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': + resolution: {integrity: sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==} cpu: [riscv64] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': - resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} + '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': + resolution: {integrity: sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==} cpu: [riscv64] os: [linux] libc: [musl] - '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': - resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} + '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': + resolution: {integrity: sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==} cpu: [s390x] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-x64-gnu@1.11.1': - resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} + '@unrs/resolver-binding-linux-x64-gnu@1.12.2': + resolution: {integrity: sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==} cpu: [x64] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-x64-musl@1.11.1': - resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} + '@unrs/resolver-binding-linux-x64-musl@1.12.2': + resolution: {integrity: sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==} cpu: [x64] os: [linux] libc: [musl] - '@unrs/resolver-binding-wasm32-wasi@1.11.1': - resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + '@unrs/resolver-binding-openharmony-arm64@1.12.2': + resolution: {integrity: sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==} + cpu: [arm64] + os: [openharmony] + + '@unrs/resolver-binding-wasm32-wasi@1.12.2': + resolution: {integrity: sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': - resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} + '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': + resolution: {integrity: sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==} cpu: [arm64] os: [win32] - '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': - resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} + '@unrs/resolver-binding-win32-ia32-msvc@1.12.2': + resolution: {integrity: sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==} cpu: [ia32] os: [win32] - '@unrs/resolver-binding-win32-x64-msvc@1.11.1': - resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} + '@unrs/resolver-binding-win32-x64-msvc@1.12.2': + resolution: {integrity: sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==} cpu: [x64] os: [win32] @@ -779,13 +806,13 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.16.0: - resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + acorn@8.17.0: + resolution: {integrity: sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==} engines: {node: '>=0.4.0'} hasBin: true - ajv@6.14.0: - resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} @@ -841,8 +868,8 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axe-core@4.11.1: - resolution: {integrity: sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==} + axe-core@4.12.1: + resolution: {integrity: sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA==} engines: {node: '>=4'} axobject-query@4.1.0: @@ -856,24 +883,24 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} - baseline-browser-mapping@2.10.29: - resolution: {integrity: sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==} + baseline-browser-mapping@2.10.37: + resolution: {integrity: sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig==} engines: {node: '>=6.0.0'} hasBin: true - brace-expansion@1.1.13: - resolution: {integrity: sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==} + brace-expansion@1.1.15: + resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==} - brace-expansion@5.0.5: - resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + brace-expansion@5.0.6: + resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} engines: {node: 18 || 20 || >=22} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.28.1: - resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + browserslist@4.28.2: + resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -881,8 +908,8 @@ packages: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} - call-bind@1.0.8: - resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + call-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} engines: {node: '>= 0.4'} call-bound@1.0.4: @@ -893,8 +920,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001792: - resolution: {integrity: sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==} + caniuse-lite@1.0.30001799: + resolution: {integrity: sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -976,8 +1003,8 @@ packages: dexie: '>=4.2.0-alpha.1 <5.0.0' react: '>=16' - dexie@4.4.2: - resolution: {integrity: sha512-zMtV8q79EFE5U8FKZvt0Y/77PCU/Hr/RDxv1EDeo228L+m/HTbeN2AjoQm674rhQCX8n3ljK87lajt7UQuZfvw==} + dexie@4.4.3: + resolution: {integrity: sha512-N+3IGQ3HPlyO2YAkntGAwitm42BpBGV86MttzUMiRzWLa4NGh0pltVRcUVF4ybL/OnXjCrr9k7SDPIKkFYP2Lg==} doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} @@ -987,18 +1014,18 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - electron-to-chromium@1.5.328: - resolution: {integrity: sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w==} + electron-to-chromium@1.5.372: + resolution: {integrity: sha512-M3yhbAlilnwqC8D21t28UCDGHyitShTmmLRU/H+b74P6Ski16Nb9HONYEaVpMj/pwC7BEo5B95FpjODLCWbtfA==} emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - enhanced-resolve@5.20.1: - resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==} + enhanced-resolve@5.21.6: + resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==} engines: {node: '>=10.13.0'} - es-abstract@1.24.1: - resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} + es-abstract@1.24.2: + resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==} engines: {node: '>= 0.4'} es-define-property@1.0.1: @@ -1009,12 +1036,12 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-iterator-helpers@1.3.1: - resolution: {integrity: sha512-zWwRvqWiuBPr0muUG/78cW3aHROFCNIQ3zpmYDpwdbnt2m+xlNyRWpHBpa2lJjSBit7BQ+RXA1iwbSmu5yJ/EQ==} + es-iterator-helpers@1.3.3: + resolution: {integrity: sha512-0PuBxFi+4uPanB97iDxCLWuHeYud2FALrw5HFZGtAF38UpJDbDC8frwp2cnDyae692CQ0dou60UwWfhgsa4U/g==} engines: {node: '>= 0.4'} - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} engines: {node: '>= 0.4'} es-set-tostringtag@2.1.0: @@ -1046,8 +1073,8 @@ packages: typescript: optional: true - eslint-import-resolver-node@0.3.9: - resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + eslint-import-resolver-node@0.3.10: + resolution: {integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==} eslint-import-resolver-typescript@3.10.1: resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==} @@ -1062,8 +1089,8 @@ packages: eslint-plugin-import-x: optional: true - eslint-module-utils@2.12.1: - resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} + eslint-module-utils@2.13.0: + resolution: {integrity: sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -1099,11 +1126,11 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - eslint-plugin-react-hooks@7.0.1: - resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==} + eslint-plugin-react-hooks@7.1.1: + resolution: {integrity: sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==} engines: {node: '>=18'} peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0 eslint-plugin-react@7.37.5: resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} @@ -1208,8 +1235,8 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - function.prototype.name@1.1.8: - resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + function.prototype.name@1.2.0: + resolution: {integrity: sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==} engines: {node: '>= 0.4'} functions-have-names@1.2.3: @@ -1235,8 +1262,8 @@ packages: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - get-tsconfig@4.13.7: - resolution: {integrity: sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==} + get-tsconfig@4.14.0: + resolution: {integrity: sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==} glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -1288,8 +1315,8 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} hermes-estree@0.25.1: @@ -1341,8 +1368,8 @@ packages: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + is-core-module@2.16.2: + resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} engines: {node: '>= 0.4'} is-data-view@1.0.2: @@ -1353,6 +1380,10 @@ packages: resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} engines: {node: '>= 0.4'} + is-document.all@1.0.0: + resolution: {integrity: sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==} + engines: {node: '>= 0.4'} + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -1431,15 +1462,15 @@ packages: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} - jiti@2.6.1: - resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} hasBin: true js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@4.1.1: - resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + js-yaml@4.2.0: + resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} hasBin: true jsesc@3.1.0: @@ -1589,8 +1620,8 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - minimatch@10.2.4: - resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} engines: {node: 18 || 20 || >=22} minimatch@3.1.5: @@ -1602,11 +1633,6 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - nanoid@3.3.12: resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -1645,8 +1671,9 @@ packages: resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==} engines: {node: '>= 0.4'} - node-releases@2.0.36: - resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} + node-releases@2.0.47: + resolution: {integrity: sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==} + engines: {node: '>=18'} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -1730,8 +1757,8 @@ packages: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} - postcss@8.5.8: - resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -1775,13 +1802,8 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve@1.22.11: - resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} - engines: {node: '>= 0.4'} - hasBin: true - - resolve@2.0.0-next.6: - resolution: {integrity: sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==} + resolve@2.0.0-next.7: + resolution: {integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==} engines: {node: '>= 0.4'} hasBin: true @@ -1792,8 +1814,8 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - safe-array-concat@1.1.3: - resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + safe-array-concat@1.1.4: + resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==} engines: {node: '>=0.4'} safe-push-apply@1.0.0: @@ -1811,8 +1833,8 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.8.0: - resolution: {integrity: sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==} + semver@7.8.4: + resolution: {integrity: sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==} engines: {node: '>=10'} hasBin: true @@ -1840,8 +1862,8 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} engines: {node: '>= 0.4'} side-channel-map@1.0.1: @@ -1852,8 +1874,8 @@ packages: resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} engines: {node: '>= 0.4'} - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} engines: {node: '>= 0.4'} source-map-js@1.2.1: @@ -1878,12 +1900,12 @@ packages: string.prototype.repeat@1.0.0: resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} - string.prototype.trim@1.2.10: - resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + string.prototype.trim@1.2.11: + resolution: {integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==} engines: {node: '>= 0.4'} - string.prototype.trimend@1.0.9: - resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + string.prototype.trimend@1.0.10: + resolution: {integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==} engines: {node: '>= 0.4'} string.prototype.trimstart@1.0.8: @@ -1919,15 +1941,15 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - tailwindcss@4.2.2: - resolution: {integrity: sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==} + tailwindcss@4.3.1: + resolution: {integrity: sha512-hk+TB1m+K8CYNrP6rjQaq/Y+4Zylwpa87mLYBKCunwnnQ9p+fHb7kmSfGqyEJoxF/O6CDyABWVFEafNSYKll+Q==} - tapable@2.3.2: - resolution: {integrity: sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==} + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} engines: {node: '>=6'} - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} to-regex-range@5.0.1: @@ -1962,16 +1984,16 @@ packages: resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} engines: {node: '>= 0.4'} - typed-array-length@1.0.7: - resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + typed-array-length@1.0.8: + resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==} engines: {node: '>= 0.4'} - typescript-eslint@8.57.2: - resolution: {integrity: sha512-VEPQ0iPgWO/sBaZOU1xo4nuNdODVOajPnTIbog2GKYr31nIlZ0fWPoCQgGfF3ETyBl1vn63F/p50Um9Z4J8O8A==} + typescript-eslint@8.61.0: + resolution: {integrity: sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} @@ -1985,8 +2007,8 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - unrs-resolver@1.11.1: - resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + unrs-resolver@1.12.2: + resolution: {integrity: sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==} update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} @@ -2009,8 +2031,8 @@ packages: resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} engines: {node: '>= 0.4'} - which-typed-array@1.1.20: - resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} + which-typed-array@1.1.22: + resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} engines: {node: '>= 0.4'} which@2.0.2: @@ -2035,32 +2057,32 @@ packages: peerDependencies: zod: ^3.25.0 || ^4.0.0 - zod@4.3.6: - resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} snapshots: '@alloc/quick-lru@5.2.0': {} - '@babel/code-frame@7.29.0': + '@babel/code-frame@7.29.7': dependencies: - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-validator-identifier': 7.29.7 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.29.0': {} + '@babel/compat-data@7.29.7': {} - '@babel/core@7.29.0': + '@babel/core@7.29.7': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helpers': 7.29.2 - '@babel/parser': 7.29.2 - '@babel/template': 7.28.6 - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -2070,81 +2092,81 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.29.1': + '@babel/generator@7.29.7': dependencies: - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - '@babel/helper-compilation-targets@7.28.6': + '@babel/helper-compilation-targets@7.29.7': dependencies: - '@babel/compat-data': 7.29.0 - '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.1 + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.28.2 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-globals@7.28.0': {} + '@babel/helper-globals@7.29.7': {} - '@babel/helper-module-imports@7.28.6': + '@babel/helper-module-imports@7.29.7': dependencies: - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.29.0 + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.7 transitivePeerDependencies: - supports-color - '@babel/helper-string-parser@7.27.1': {} + '@babel/helper-string-parser@7.29.7': {} - '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-identifier@7.29.7': {} - '@babel/helper-validator-option@7.27.1': {} + '@babel/helper-validator-option@7.29.7': {} - '@babel/helpers@7.29.2': + '@babel/helpers@7.29.7': dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 - '@babel/parser@7.29.2': + '@babel/parser@7.29.7': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 - '@babel/template@7.28.6': + '@babel/template@7.29.7': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 - '@babel/traverse@7.29.0': + '@babel/traverse@7.29.7': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.2 - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 debug: 4.4.3 transitivePeerDependencies: - supports-color - '@babel/types@7.29.0': + '@babel/types@7.29.7': dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 - '@emnapi/core@1.9.1': + '@emnapi/core@1.10.0': dependencies: - '@emnapi/wasi-threads': 1.2.0 + '@emnapi/wasi-threads': 1.2.1 tslib: 2.8.1 optional: true @@ -2153,14 +2175,19 @@ snapshots: tslib: 2.8.1 optional: true - '@emnapi/wasi-threads@1.2.0': + '@emnapi/runtime@1.11.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.1': dependencies: tslib: 2.8.1 optional: true - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.7.0))': dependencies: - eslint: 9.39.4(jiti@2.6.1) + eslint: 9.39.4(jiti@2.7.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -2183,13 +2210,13 @@ snapshots: '@eslint/eslintrc@3.3.5': dependencies: - ajv: 6.14.0 + ajv: 6.15.0 debug: 4.4.3 espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 - js-yaml: 4.1.1 + js-yaml: 4.2.0 minimatch: 3.1.5 strip-json-comments: 3.1.1 transitivePeerDependencies: @@ -2204,7 +2231,7 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 - '@folderharbor/sdk@1.1.1': {} + '@folderharbor/sdk@1.1.2': {} '@fortawesome/fontawesome-common-types@7.2.0': {} @@ -2224,18 +2251,23 @@ snapshots: dependencies: '@fortawesome/fontawesome-common-types': 7.2.0 - '@fortawesome/react-fontawesome@3.3.0(@fortawesome/fontawesome-svg-core@7.2.0)(react@19.2.6)': + '@fortawesome/react-fontawesome@3.3.1(@fortawesome/fontawesome-svg-core@7.2.0)(react@19.2.6)': dependencies: '@fortawesome/fontawesome-svg-core': 7.2.0 react: 19.2.6 - '@humanfs/core@0.19.1': {} + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 - '@humanfs/node@0.16.7': + '@humanfs/node@0.16.8': dependencies: - '@humanfs/core': 0.19.1 + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 '@humanwhocodes/retry': 0.4.3 + '@humanfs/types@0.15.0': {} + '@humanwhocodes/module-importer@1.0.1': {} '@humanwhocodes/retry@0.4.3': {} @@ -2325,7 +2357,7 @@ snapshots: '@img/sharp-wasm32@0.34.5': dependencies: - '@emnapi/runtime': 1.10.0 + '@emnapi/runtime': 1.11.1 optional: true '@img/sharp-win32-arm64@0.34.5': @@ -2356,11 +2388,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@napi-rs/wasm-runtime@0.2.12': + '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: - '@emnapi/core': 1.9.1 + '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 - '@tybys/wasm-util': 0.10.1 + '@tybys/wasm-util': 0.10.2 optional: true '@next/env@16.2.6': {} @@ -2413,81 +2445,81 @@ snapshots: dependencies: tslib: 2.8.1 - '@tailwindcss/node@4.2.2': + '@tailwindcss/node@4.3.1': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.20.1 - jiti: 2.6.1 + enhanced-resolve: 5.21.6 + jiti: 2.7.0 lightningcss: 1.32.0 magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.2.2 + tailwindcss: 4.3.1 - '@tailwindcss/oxide-android-arm64@4.2.2': + '@tailwindcss/oxide-android-arm64@4.3.1': optional: true - '@tailwindcss/oxide-darwin-arm64@4.2.2': + '@tailwindcss/oxide-darwin-arm64@4.3.1': optional: true - '@tailwindcss/oxide-darwin-x64@4.2.2': + '@tailwindcss/oxide-darwin-x64@4.3.1': optional: true - '@tailwindcss/oxide-freebsd-x64@4.2.2': + '@tailwindcss/oxide-freebsd-x64@4.3.1': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.1': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': + '@tailwindcss/oxide-linux-arm64-gnu@4.3.1': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.2.2': + '@tailwindcss/oxide-linux-arm64-musl@4.3.1': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.2.2': + '@tailwindcss/oxide-linux-x64-gnu@4.3.1': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.2.2': + '@tailwindcss/oxide-linux-x64-musl@4.3.1': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.2.2': + '@tailwindcss/oxide-wasm32-wasi@4.3.1': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': + '@tailwindcss/oxide-win32-arm64-msvc@4.3.1': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.2.2': + '@tailwindcss/oxide-win32-x64-msvc@4.3.1': optional: true - '@tailwindcss/oxide@4.2.2': + '@tailwindcss/oxide@4.3.1': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.2.2 - '@tailwindcss/oxide-darwin-arm64': 4.2.2 - '@tailwindcss/oxide-darwin-x64': 4.2.2 - '@tailwindcss/oxide-freebsd-x64': 4.2.2 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.2 - '@tailwindcss/oxide-linux-arm64-gnu': 4.2.2 - '@tailwindcss/oxide-linux-arm64-musl': 4.2.2 - '@tailwindcss/oxide-linux-x64-gnu': 4.2.2 - '@tailwindcss/oxide-linux-x64-musl': 4.2.2 - '@tailwindcss/oxide-wasm32-wasi': 4.2.2 - '@tailwindcss/oxide-win32-arm64-msvc': 4.2.2 - '@tailwindcss/oxide-win32-x64-msvc': 4.2.2 - - '@tailwindcss/postcss@4.2.2': + '@tailwindcss/oxide-android-arm64': 4.3.1 + '@tailwindcss/oxide-darwin-arm64': 4.3.1 + '@tailwindcss/oxide-darwin-x64': 4.3.1 + '@tailwindcss/oxide-freebsd-x64': 4.3.1 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.1 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.1 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.1 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.1 + '@tailwindcss/oxide-linux-x64-musl': 4.3.1 + '@tailwindcss/oxide-wasm32-wasi': 4.3.1 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.1 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.1 + + '@tailwindcss/postcss@4.3.1': dependencies: '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.2.2 - '@tailwindcss/oxide': 4.2.2 - postcss: 8.5.8 - tailwindcss: 4.2.2 + '@tailwindcss/node': 4.3.1 + '@tailwindcss/oxide': 4.3.1 + postcss: 8.5.15 + tailwindcss: 4.3.1 - '@tybys/wasm-util@0.10.1': + '@tybys/wasm-util@0.10.2': dependencies: tslib: 2.8.1 optional: true - '@types/estree@1.0.8': {} + '@types/estree@1.0.9': {} '@types/json-schema@7.0.15': {} @@ -2499,7 +2531,7 @@ snapshots: '@types/lodash@4.17.24': {} - '@types/node@20.19.37': + '@types/node@20.19.43': dependencies: undici-types: 6.21.0 @@ -2511,15 +2543,15 @@ snapshots: dependencies: csstype: 3.2.3 - '@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.61.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.57.2 - '@typescript-eslint/type-utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.57.2 - eslint: 9.39.4(jiti@2.6.1) + '@typescript-eslint/parser': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.61.0 + '@typescript-eslint/type-utils': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/utils': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.61.0 + eslint: 9.39.4(jiti@2.7.0) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@5.9.3) @@ -2527,147 +2559,158 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.57.2 - '@typescript-eslint/types': 8.57.2 - '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.57.2 + '@typescript-eslint/scope-manager': 8.61.0 + '@typescript-eslint/types': 8.61.0 + '@typescript-eslint/typescript-estree': 8.61.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.61.0 debug: 4.4.3 - eslint: 9.39.4(jiti@2.6.1) + eslint: 9.39.4(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.57.2(typescript@5.9.3)': + '@typescript-eslint/project-service@8.61.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.57.2(typescript@5.9.3) - '@typescript-eslint/types': 8.57.2 + '@typescript-eslint/tsconfig-utils': 8.61.0(typescript@5.9.3) + '@typescript-eslint/types': 8.61.0 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.57.2': + '@typescript-eslint/scope-manager@8.61.0': dependencies: - '@typescript-eslint/types': 8.57.2 - '@typescript-eslint/visitor-keys': 8.57.2 + '@typescript-eslint/types': 8.61.0 + '@typescript-eslint/visitor-keys': 8.61.0 - '@typescript-eslint/tsconfig-utils@8.57.2(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.61.0(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.57.2 - '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/types': 8.61.0 + '@typescript-eslint/typescript-estree': 8.61.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) debug: 4.4.3 - eslint: 9.39.4(jiti@2.6.1) + eslint: 9.39.4(jiti@2.7.0) ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.57.2': {} + '@typescript-eslint/types@8.61.0': {} - '@typescript-eslint/typescript-estree@8.57.2(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.61.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.57.2(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.57.2(typescript@5.9.3) - '@typescript-eslint/types': 8.57.2 - '@typescript-eslint/visitor-keys': 8.57.2 + '@typescript-eslint/project-service': 8.61.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.61.0(typescript@5.9.3) + '@typescript-eslint/types': 8.61.0 + '@typescript-eslint/visitor-keys': 8.61.0 debug: 4.4.3 - minimatch: 10.2.4 - semver: 7.8.0 - tinyglobby: 0.2.15 + minimatch: 10.2.5 + semver: 7.8.4 + tinyglobby: 0.2.17 ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/utils@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.57.2 - '@typescript-eslint/types': 8.57.2 - '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) - eslint: 9.39.4(jiti@2.6.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.7.0)) + '@typescript-eslint/scope-manager': 8.61.0 + '@typescript-eslint/types': 8.61.0 + '@typescript-eslint/typescript-estree': 8.61.0(typescript@5.9.3) + eslint: 9.39.4(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.57.2': + '@typescript-eslint/visitor-keys@8.61.0': dependencies: - '@typescript-eslint/types': 8.57.2 + '@typescript-eslint/types': 8.61.0 eslint-visitor-keys: 5.0.1 - '@unrs/resolver-binding-android-arm-eabi@1.11.1': + '@unrs/resolver-binding-android-arm-eabi@1.12.2': + optional: true + + '@unrs/resolver-binding-android-arm64@1.12.2': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.12.2': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.12.2': optional: true - '@unrs/resolver-binding-android-arm64@1.11.1': + '@unrs/resolver-binding-freebsd-x64@1.12.2': optional: true - '@unrs/resolver-binding-darwin-arm64@1.11.1': + '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2': optional: true - '@unrs/resolver-binding-darwin-x64@1.11.1': + '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2': optional: true - '@unrs/resolver-binding-freebsd-x64@1.11.1': + '@unrs/resolver-binding-linux-arm64-gnu@1.12.2': optional: true - '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + '@unrs/resolver-binding-linux-arm64-musl@1.12.2': optional: true - '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': optional: true - '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + '@unrs/resolver-binding-linux-loong64-musl@1.12.2': optional: true - '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': optional: true - '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': optional: true - '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': optional: true - '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': optional: true - '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + '@unrs/resolver-binding-linux-x64-gnu@1.12.2': optional: true - '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + '@unrs/resolver-binding-linux-x64-musl@1.12.2': optional: true - '@unrs/resolver-binding-linux-x64-musl@1.11.1': + '@unrs/resolver-binding-openharmony-arm64@1.12.2': optional: true - '@unrs/resolver-binding-wasm32-wasi@1.11.1': + '@unrs/resolver-binding-wasm32-wasi@1.12.2': dependencies: - '@napi-rs/wasm-runtime': 0.2.12 + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': optional: true - '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + '@unrs/resolver-binding-win32-ia32-msvc@1.12.2': optional: true - '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + '@unrs/resolver-binding-win32-x64-msvc@1.12.2': optional: true - acorn-jsx@5.3.2(acorn@8.16.0): + acorn-jsx@5.3.2(acorn@8.17.0): dependencies: - acorn: 8.16.0 + acorn: 8.17.0 - acorn@8.16.0: {} + acorn@8.17.0: {} - ajv@6.14.0: + ajv@6.15.0: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 @@ -2689,62 +2732,62 @@ snapshots: array-includes@3.1.9: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 get-intrinsic: 1.3.0 is-string: 1.1.1 math-intrinsics: 1.1.0 array.prototype.findlast@1.2.5: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 es-shim-unscopables: 1.1.0 array.prototype.findlastindex@1.2.6: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 es-shim-unscopables: 1.1.0 array.prototype.flat@1.3.3: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-shim-unscopables: 1.1.0 array.prototype.flatmap@1.3.3: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-shim-unscopables: 1.1.0 array.prototype.tosorted@1.1.4: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-errors: 1.3.0 es-shim-unscopables: 1.1.0 arraybuffer.prototype.slice@1.0.4: dependencies: array-buffer-byte-length: 1.0.2 - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-errors: 1.3.0 get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 @@ -2757,7 +2800,7 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 - axe-core@4.11.1: {} + axe-core@4.12.1: {} axobject-query@4.1.0: {} @@ -2765,14 +2808,14 @@ snapshots: balanced-match@4.0.4: {} - baseline-browser-mapping@2.10.29: {} + baseline-browser-mapping@2.10.37: {} - brace-expansion@1.1.13: + brace-expansion@1.1.15: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@5.0.5: + brace-expansion@5.0.6: dependencies: balanced-match: 4.0.4 @@ -2780,20 +2823,20 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.28.1: + browserslist@4.28.2: dependencies: - baseline-browser-mapping: 2.10.29 - caniuse-lite: 1.0.30001792 - electron-to-chromium: 1.5.328 - node-releases: 2.0.36 - update-browserslist-db: 1.2.3(browserslist@4.28.1) + baseline-browser-mapping: 2.10.37 + caniuse-lite: 1.0.30001799 + electron-to-chromium: 1.5.372 + node-releases: 2.0.47 + update-browserslist-db: 1.2.3(browserslist@4.28.2) call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 function-bind: 1.1.2 - call-bind@1.0.8: + call-bind@1.0.9: dependencies: call-bind-apply-helpers: 1.0.2 es-define-property: 1.0.1 @@ -2807,7 +2850,7 @@ snapshots: callsites@3.1.0: {} - caniuse-lite@1.0.30001792: {} + caniuse-lite@1.0.30001799: {} chalk@4.1.2: dependencies: @@ -2878,12 +2921,12 @@ snapshots: detect-libc@2.1.2: {} - dexie-react-hooks@4.4.0(dexie@4.4.2)(react@19.2.6): + dexie-react-hooks@4.4.0(dexie@4.4.3)(react@19.2.6): dependencies: - dexie: 4.4.2 + dexie: 4.4.3 react: 19.2.6 - dexie@4.4.2: {} + dexie@4.4.3: {} doctrine@2.1.0: dependencies: @@ -2895,31 +2938,31 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - electron-to-chromium@1.5.328: {} + electron-to-chromium@1.5.372: {} emoji-regex@9.2.2: {} - enhanced-resolve@5.20.1: + enhanced-resolve@5.21.6: dependencies: graceful-fs: 4.2.11 - tapable: 2.3.2 + tapable: 2.3.3 - es-abstract@1.24.1: + es-abstract@1.24.2: dependencies: array-buffer-byte-length: 1.0.2 arraybuffer.prototype.slice: 1.0.4 available-typed-arrays: 1.0.7 - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 data-view-buffer: 1.0.2 data-view-byte-length: 1.0.2 data-view-byte-offset: 1.0.1 es-define-property: 1.0.1 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 es-set-tostringtag: 2.1.0 es-to-primitive: 1.3.0 - function.prototype.name: 1.1.8 + function.prototype.name: 1.2.0 get-intrinsic: 1.3.0 get-proto: 1.0.1 get-symbol-description: 1.1.0 @@ -2928,7 +2971,7 @@ snapshots: has-property-descriptors: 1.0.2 has-proto: 1.2.0 has-symbols: 1.1.0 - hasown: 2.0.2 + hasown: 2.0.4 internal-slot: 1.1.0 is-array-buffer: 3.0.5 is-callable: 1.2.7 @@ -2946,31 +2989,31 @@ snapshots: object.assign: 4.1.7 own-keys: 1.0.1 regexp.prototype.flags: 1.5.4 - safe-array-concat: 1.1.3 + safe-array-concat: 1.1.4 safe-push-apply: 1.0.0 safe-regex-test: 1.1.0 set-proto: 1.0.0 stop-iteration-iterator: 1.1.0 - string.prototype.trim: 1.2.10 - string.prototype.trimend: 1.0.9 + string.prototype.trim: 1.2.11 + string.prototype.trimend: 1.0.10 string.prototype.trimstart: 1.0.8 typed-array-buffer: 1.0.3 typed-array-byte-length: 1.0.3 typed-array-byte-offset: 1.0.4 - typed-array-length: 1.0.7 + typed-array-length: 1.0.8 unbox-primitive: 1.1.0 - which-typed-array: 1.1.20 + which-typed-array: 1.1.22 es-define-property@1.0.1: {} es-errors@1.3.0: {} - es-iterator-helpers@1.3.1: + es-iterator-helpers@1.3.3: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-errors: 1.3.0 es-set-tostringtag: 2.1.0 function-bind: 1.1.2 @@ -2983,9 +3026,8 @@ snapshots: internal-slot: 1.1.0 iterator.prototype: 1.1.5 math-intrinsics: 1.1.0 - safe-array-concat: 1.1.3 - es-object-atoms@1.1.1: + es-object-atoms@1.1.2: dependencies: es-errors: 1.3.0 @@ -2994,11 +3036,11 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 has-tostringtag: 1.0.2 - hasown: 2.0.2 + hasown: 2.0.4 es-shim-unscopables@1.1.0: dependencies: - hasown: 2.0.2 + hasown: 2.0.4 es-to-primitive@1.3.0: dependencies: @@ -3010,18 +3052,18 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-next@16.2.6(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3): + eslint-config-next@16.2.6(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3): dependencies: '@next/eslint-plugin-next': 16.2.6 - eslint: 9.39.4(jiti@2.6.1) - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.4(jiti@2.6.1)) - eslint-plugin-react: 7.37.5(eslint@9.39.4(jiti@2.6.1)) - eslint-plugin-react-hooks: 7.0.1(eslint@9.39.4(jiti@2.6.1)) + eslint: 9.39.4(jiti@2.7.0) + eslint-import-resolver-node: 0.3.10 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.7.0)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.4(jiti@2.7.0)) + eslint-plugin-react: 7.37.5(eslint@9.39.4(jiti@2.7.0)) + eslint-plugin-react-hooks: 7.1.1(eslint@9.39.4(jiti@2.7.0)) globals: 16.4.0 - typescript-eslint: 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + typescript-eslint: 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -3030,41 +3072,41 @@ snapshots: - eslint-plugin-import-x - supports-color - eslint-import-resolver-node@0.3.9: + eslint-import-resolver-node@0.3.10: dependencies: debug: 3.2.7 - is-core-module: 2.16.1 - resolve: 1.22.11 + is-core-module: 2.16.2 + resolve: 2.0.0-next.7 transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.7.0)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.3 - eslint: 9.39.4(jiti@2.6.1) - get-tsconfig: 4.13.7 + eslint: 9.39.4(jiti@2.7.0) + get-tsconfig: 4.14.0 is-bun-module: 2.0.0 stable-hash: 0.0.5 - tinyglobby: 0.2.15 - unrs-resolver: 1.11.1 + tinyglobby: 0.2.17 + unrs-resolver: 1.12.2 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)): + eslint-module-utils@2.13.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.39.4(jiti@2.6.1) - eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)) + '@typescript-eslint/parser': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + eslint: 9.39.4(jiti@2.7.0) + eslint-import-resolver-node: 0.3.10 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.7.0)) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.6.1)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -3073,38 +3115,38 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.39.4(jiti@2.6.1) - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)))(eslint@9.39.4(jiti@2.6.1)) - hasown: 2.0.2 - is-core-module: 2.16.1 + eslint: 9.39.4(jiti@2.7.0) + eslint-import-resolver-node: 0.3.10 + eslint-module-utils: 2.13.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0)) + hasown: 2.0.4 + is-core-module: 2.16.2 is-glob: 4.0.3 minimatch: 3.1.5 object.fromentries: 2.0.8 object.groupby: 1.0.3 object.values: 1.2.1 semver: 6.3.1 - string.prototype.trimend: 1.0.9 + string.prototype.trimend: 1.0.10 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.4(jiti@2.6.1)): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.4(jiti@2.7.0)): dependencies: aria-query: 5.3.2 array-includes: 3.1.9 array.prototype.flatmap: 1.3.3 ast-types-flow: 0.0.8 - axe-core: 4.11.1 + axe-core: 4.12.1 axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 9.39.4(jiti@2.6.1) - hasown: 2.0.2 + eslint: 9.39.4(jiti@2.7.0) + hasown: 2.0.4 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 minimatch: 3.1.5 @@ -3112,35 +3154,35 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-react-hooks@7.0.1(eslint@9.39.4(jiti@2.6.1)): + eslint-plugin-react-hooks@7.1.1(eslint@9.39.4(jiti@2.7.0)): dependencies: - '@babel/core': 7.29.0 - '@babel/parser': 7.29.2 - eslint: 9.39.4(jiti@2.6.1) + '@babel/core': 7.29.7 + '@babel/parser': 7.29.7 + eslint: 9.39.4(jiti@2.7.0) hermes-parser: 0.25.1 - zod: 4.3.6 - zod-validation-error: 4.0.2(zod@4.3.6) + zod: 4.4.3 + zod-validation-error: 4.0.2(zod@4.4.3) transitivePeerDependencies: - supports-color - eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.6.1)): + eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.7.0)): dependencies: array-includes: 3.1.9 array.prototype.findlast: 1.2.5 array.prototype.flatmap: 1.3.3 array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 - es-iterator-helpers: 1.3.1 - eslint: 9.39.4(jiti@2.6.1) + es-iterator-helpers: 1.3.3 + eslint: 9.39.4(jiti@2.7.0) estraverse: 5.3.0 - hasown: 2.0.2 + hasown: 2.0.4 jsx-ast-utils: 3.3.5 minimatch: 3.1.5 object.entries: 1.1.9 object.fromentries: 2.0.8 object.values: 1.2.1 prop-types: 15.8.1 - resolve: 2.0.0-next.6 + resolve: 2.0.0-next.7 semver: 6.3.1 string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 @@ -3156,9 +3198,9 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@9.39.4(jiti@2.6.1): + eslint@9.39.4(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.7.0)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.2 '@eslint/config-helpers': 0.4.2 @@ -3166,11 +3208,11 @@ snapshots: '@eslint/eslintrc': 3.3.5 '@eslint/js': 9.39.4 '@eslint/plugin-kit': 0.4.1 - '@humanfs/node': 0.16.7 + '@humanfs/node': 0.16.8 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 - ajv: 6.14.0 + '@types/estree': 1.0.9 + ajv: 6.15.0 chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.3 @@ -3193,14 +3235,14 @@ snapshots: natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: - jiti: 2.6.1 + jiti: 2.7.0 transitivePeerDependencies: - supports-color espree@10.4.0: dependencies: - acorn: 8.16.0 - acorn-jsx: 5.3.2(acorn@8.16.0) + acorn: 8.17.0 + acorn-jsx: 5.3.2(acorn@8.17.0) eslint-visitor-keys: 4.2.1 esquery@1.7.0: @@ -3263,14 +3305,17 @@ snapshots: function-bind@1.1.2: {} - function.prototype.name@1.1.8: + function.prototype.name@1.2.0: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 - define-properties: 1.2.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 functions-have-names: 1.2.3 - hasown: 2.0.2 + has-property-descriptors: 1.0.2 + hasown: 2.0.4 is-callable: 1.2.7 + is-document.all: 1.0.0 functions-have-names@1.2.3: {} @@ -3283,18 +3328,18 @@ snapshots: call-bind-apply-helpers: 1.0.2 es-define-property: 1.0.1 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 function-bind: 1.1.2 get-proto: 1.0.1 gopd: 1.2.0 has-symbols: 1.1.0 - hasown: 2.0.2 + hasown: 2.0.4 math-intrinsics: 1.1.0 get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 get-symbol-description@1.1.0: dependencies: @@ -3302,7 +3347,7 @@ snapshots: es-errors: 1.3.0 get-intrinsic: 1.3.0 - get-tsconfig@4.13.7: + get-tsconfig@4.14.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -3345,7 +3390,7 @@ snapshots: dependencies: has-symbols: 1.1.0 - hasown@2.0.2: + hasown@2.0.4: dependencies: function-bind: 1.1.2 @@ -3369,12 +3414,12 @@ snapshots: internal-slot@1.1.0: dependencies: es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.1.0 + hasown: 2.0.4 + side-channel: 1.1.1 is-array-buffer@3.0.5: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 get-intrinsic: 1.3.0 @@ -3397,13 +3442,13 @@ snapshots: is-bun-module@2.0.0: dependencies: - semver: 7.8.0 + semver: 7.8.4 is-callable@1.2.7: {} - is-core-module@2.16.1: + is-core-module@2.16.2: dependencies: - hasown: 2.0.2 + hasown: 2.0.4 is-data-view@1.0.2: dependencies: @@ -3416,6 +3461,10 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 + is-document.all@1.0.0: + dependencies: + call-bound: 1.0.4 + is-extglob@2.1.1: {} is-finalizationregistry@1.1.1: @@ -3450,7 +3499,7 @@ snapshots: call-bound: 1.0.4 gopd: 1.2.0 has-tostringtag: 1.0.2 - hasown: 2.0.2 + hasown: 2.0.4 is-set@2.0.3: {} @@ -3471,7 +3520,7 @@ snapshots: is-typed-array@1.1.15: dependencies: - which-typed-array: 1.1.20 + which-typed-array: 1.1.22 is-weakmap@2.0.2: {} @@ -3491,17 +3540,17 @@ snapshots: iterator.prototype@1.1.5: dependencies: define-data-property: 1.1.4 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 get-intrinsic: 1.3.0 get-proto: 1.0.1 has-symbols: 1.1.0 set-function-name: 2.0.2 - jiti@2.6.1: {} + jiti@2.7.0: {} js-tokens@4.0.0: {} - js-yaml@4.1.1: + js-yaml@4.2.0: dependencies: argparse: 2.0.1 @@ -3619,36 +3668,34 @@ snapshots: braces: 3.0.3 picomatch: 2.3.2 - minimatch@10.2.4: + minimatch@10.2.5: dependencies: - brace-expansion: 5.0.5 + brace-expansion: 5.0.6 minimatch@3.1.5: dependencies: - brace-expansion: 1.1.13 + brace-expansion: 1.1.15 minimist@1.2.8: {} ms@2.1.3: {} - nanoid@3.3.11: {} - nanoid@3.3.12: {} napi-postinstall@0.3.4: {} natural-compare@1.4.0: {} - next@16.2.6(@babel/core@7.29.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): + next@16.2.6(@babel/core@7.29.7)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: '@next/env': 16.2.6 '@swc/helpers': 0.5.15 - baseline-browser-mapping: 2.10.29 - caniuse-lite: 1.0.30001792 + baseline-browser-mapping: 2.10.37 + caniuse-lite: 1.0.30001799 postcss: 8.4.31 react: 19.2.6 react-dom: 19.2.6(react@19.2.6) - styled-jsx: 5.1.6(@babel/core@7.29.0)(react@19.2.6) + styled-jsx: 5.1.6(@babel/core@7.29.7)(react@19.2.6) optionalDependencies: '@next/swc-darwin-arm64': 16.2.6 '@next/swc-darwin-x64': 16.2.6 @@ -3670,7 +3717,7 @@ snapshots: object.entries: 1.1.9 semver: 6.3.1 - node-releases@2.0.36: {} + node-releases@2.0.47: {} object-assign@4.1.1: {} @@ -3680,39 +3727,39 @@ snapshots: object.assign@4.1.7: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 has-symbols: 1.1.0 object-keys: 1.1.1 object.entries@1.1.9: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 object.fromentries@2.0.8: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 object.groupby@1.0.3: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 object.values@1.2.1: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 optionator@0.9.4: dependencies: @@ -3761,9 +3808,9 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 - postcss@8.5.8: + postcss@8.5.15: dependencies: - nanoid: 3.3.11 + nanoid: 3.3.12 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -3790,18 +3837,18 @@ snapshots: reflect.getprototypeof@1.0.10: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 get-intrinsic: 1.3.0 get-proto: 1.0.1 which-builtin-type: 1.2.1 regexp.prototype.flags@1.5.4: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 es-errors: 1.3.0 get-proto: 1.0.1 @@ -3812,16 +3859,10 @@ snapshots: resolve-pkg-maps@1.0.0: {} - resolve@1.22.11: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - resolve@2.0.0-next.6: + resolve@2.0.0-next.7: dependencies: es-errors: 1.3.0 - is-core-module: 2.16.1 + is-core-module: 2.16.2 node-exports-info: 1.6.0 object-keys: 1.1.1 path-parse: 1.0.7 @@ -3833,9 +3874,9 @@ snapshots: dependencies: queue-microtask: 1.2.3 - safe-array-concat@1.1.3: + safe-array-concat@1.1.4: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 get-intrinsic: 1.3.0 has-symbols: 1.1.0 @@ -3856,7 +3897,7 @@ snapshots: semver@6.3.1: {} - semver@7.8.0: {} + semver@7.8.4: {} set-function-length@1.2.2: dependencies: @@ -3878,13 +3919,13 @@ snapshots: dependencies: dunder-proto: 1.0.1 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 sharp@0.34.5: dependencies: '@img/colour': 1.1.0 detect-libc: 2.1.2 - semver: 7.8.0 + semver: 7.8.4 optionalDependencies: '@img/sharp-darwin-arm64': 0.34.5 '@img/sharp-darwin-x64': 0.34.5 @@ -3918,7 +3959,7 @@ snapshots: shebang-regex@3.0.0: {} - side-channel-list@1.0.0: + side-channel-list@1.0.1: dependencies: es-errors: 1.3.0 object-inspect: 1.13.4 @@ -3938,11 +3979,11 @@ snapshots: object-inspect: 1.13.4 side-channel-map: 1.0.1 - side-channel@1.1.0: + side-channel@1.1.1: dependencies: es-errors: 1.3.0 object-inspect: 1.13.4 - side-channel-list: 1.0.0 + side-channel-list: 1.0.1 side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 @@ -3957,64 +3998,65 @@ snapshots: string.prototype.includes@2.0.1: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 string.prototype.matchall@4.0.12: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 es-errors: 1.3.0 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 get-intrinsic: 1.3.0 gopd: 1.2.0 has-symbols: 1.1.0 internal-slot: 1.1.0 regexp.prototype.flags: 1.5.4 set-function-name: 2.0.2 - side-channel: 1.1.0 + side-channel: 1.1.1 string.prototype.repeat@1.0.0: dependencies: define-properties: 1.2.1 - es-abstract: 1.24.1 + es-abstract: 1.24.2 - string.prototype.trim@1.2.10: + string.prototype.trim@1.2.11: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-data-property: 1.1.4 define-properties: 1.2.1 - es-abstract: 1.24.1 - es-object-atoms: 1.1.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 has-property-descriptors: 1.0.2 + safe-regex-test: 1.1.0 - string.prototype.trimend@1.0.9: + string.prototype.trimend@1.0.10: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 define-properties: 1.2.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 string.prototype.trimstart@1.0.8: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 define-properties: 1.2.1 - es-object-atoms: 1.1.1 + es-object-atoms: 1.1.2 strip-bom@3.0.0: {} strip-json-comments@3.1.1: {} - styled-jsx@5.1.6(@babel/core@7.29.0)(react@19.2.6): + styled-jsx@5.1.6(@babel/core@7.29.7)(react@19.2.6): dependencies: client-only: 0.0.1 react: 19.2.6 optionalDependencies: - '@babel/core': 7.29.0 + '@babel/core': 7.29.7 supports-color@7.2.0: dependencies: @@ -4022,11 +4064,11 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - tailwindcss@4.2.2: {} + tailwindcss@4.3.1: {} - tapable@2.3.2: {} + tapable@2.3.3: {} - tinyglobby@0.2.15: + tinyglobby@0.2.17: dependencies: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 @@ -4060,7 +4102,7 @@ snapshots: typed-array-byte-length@1.0.3: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 for-each: 0.3.5 gopd: 1.2.0 has-proto: 1.2.0 @@ -4069,29 +4111,29 @@ snapshots: typed-array-byte-offset@1.0.4: dependencies: available-typed-arrays: 1.0.7 - call-bind: 1.0.8 + call-bind: 1.0.9 for-each: 0.3.5 gopd: 1.2.0 has-proto: 1.2.0 is-typed-array: 1.1.15 reflect.getprototypeof: 1.0.10 - typed-array-length@1.0.7: + typed-array-length@1.0.8: dependencies: - call-bind: 1.0.8 + call-bind: 1.0.9 for-each: 0.3.5 gopd: 1.2.0 is-typed-array: 1.1.15 possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3): + typescript-eslint@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.57.2(@typescript-eslint/parser@8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) - '@typescript-eslint/utils': 8.57.2(eslint@9.39.4(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.39.4(jiti@2.6.1) + '@typescript-eslint/eslint-plugin': 8.61.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/parser': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.61.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) + eslint: 9.39.4(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -4107,33 +4149,36 @@ snapshots: undici-types@6.21.0: {} - unrs-resolver@1.11.1: + unrs-resolver@1.12.2: dependencies: napi-postinstall: 0.3.4 optionalDependencies: - '@unrs/resolver-binding-android-arm-eabi': 1.11.1 - '@unrs/resolver-binding-android-arm64': 1.11.1 - '@unrs/resolver-binding-darwin-arm64': 1.11.1 - '@unrs/resolver-binding-darwin-x64': 1.11.1 - '@unrs/resolver-binding-freebsd-x64': 1.11.1 - '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 - '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 - '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 - '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 - '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 - '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-x64-musl': 1.11.1 - '@unrs/resolver-binding-wasm32-wasi': 1.11.1 - '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 - '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 - '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - - update-browserslist-db@1.2.3(browserslist@4.28.1): - dependencies: - browserslist: 4.28.1 + '@unrs/resolver-binding-android-arm-eabi': 1.12.2 + '@unrs/resolver-binding-android-arm64': 1.12.2 + '@unrs/resolver-binding-darwin-arm64': 1.12.2 + '@unrs/resolver-binding-darwin-x64': 1.12.2 + '@unrs/resolver-binding-freebsd-x64': 1.12.2 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.12.2 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.12.2 + '@unrs/resolver-binding-linux-arm64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-arm64-musl': 1.12.2 + '@unrs/resolver-binding-linux-loong64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-loong64-musl': 1.12.2 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-riscv64-musl': 1.12.2 + '@unrs/resolver-binding-linux-s390x-gnu': 1.12.2 + '@unrs/resolver-binding-linux-x64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-x64-musl': 1.12.2 + '@unrs/resolver-binding-openharmony-arm64': 1.12.2 + '@unrs/resolver-binding-wasm32-wasi': 1.12.2 + '@unrs/resolver-binding-win32-arm64-msvc': 1.12.2 + '@unrs/resolver-binding-win32-ia32-msvc': 1.12.2 + '@unrs/resolver-binding-win32-x64-msvc': 1.12.2 + + update-browserslist-db@1.2.3(browserslist@4.28.2): + dependencies: + browserslist: 4.28.2 escalade: 3.2.0 picocolors: 1.1.1 @@ -4152,7 +4197,7 @@ snapshots: which-builtin-type@1.2.1: dependencies: call-bound: 1.0.4 - function.prototype.name: 1.1.8 + function.prototype.name: 1.2.0 has-tostringtag: 1.0.2 is-async-function: 2.1.1 is-date-object: 1.1.0 @@ -4163,7 +4208,7 @@ snapshots: isarray: 2.0.5 which-boxed-primitive: 1.1.1 which-collection: 1.0.2 - which-typed-array: 1.1.20 + which-typed-array: 1.1.22 which-collection@1.0.2: dependencies: @@ -4172,10 +4217,10 @@ snapshots: is-weakmap: 2.0.2 is-weakset: 2.0.4 - which-typed-array@1.1.20: + which-typed-array@1.1.22: dependencies: available-typed-arrays: 1.0.7 - call-bind: 1.0.8 + call-bind: 1.0.9 call-bound: 1.0.4 for-each: 0.3.5 get-proto: 1.0.1 @@ -4192,8 +4237,8 @@ snapshots: yocto-queue@0.1.0: {} - zod-validation-error@4.0.2(zod@4.3.6): + zod-validation-error@4.0.2(zod@4.4.3): dependencies: - zod: 4.3.6 + zod: 4.4.3 - zod@4.3.6: {} + zod@4.4.3: {} diff --git a/web/pnpm-workspace.yaml b/web/pnpm-workspace.yaml index a62c352..38bd6a9 100644 --- a/web/pnpm-workspace.yaml +++ b/web/pnpm-workspace.yaml @@ -5,5 +5,4 @@ ignoredBuiltDependencies: - sharp - unrs-resolver minimumReleaseAgeExclude: - - '@folderharbor/sdk@1.1.0' - - '@folderharbor/sdk@1.1.1' + - '@folderharbor/sdk@1.1.2' diff --git a/web/utils/api.ts b/web/utils/api.ts index 6cc44e0..19c49f9 100644 --- a/web/utils/api.ts +++ b/web/utils/api.ts @@ -1,6 +1,8 @@ -import { FHAuthError, FHPermissionError, FHRequestError } from "@folderharbor/sdk"; -export async function handleErrors(error: FHRequestError | FHAuthError | FHPermissionError): Promise<{ error: string } | { redirect: string }> { +import { Session } from "@/folderharborweb"; +import { FHAuthError, FHPermissionError, FHRequestError, FolderHarbor } from "@folderharbor/sdk"; +export function handleError(error: Error): { error: string } | { redirect: string } { if (error instanceof FHAuthError) return { redirect: `/fatal/${error.code}` } if (error instanceof FHPermissionError || error instanceof FHRequestError) return { error: `Error${error.code ? ` (${error.code})` : ""}: ${error.message}` } return { error: `Error: ${error}` } -} \ No newline at end of file +} +export function getClient(session: Session) { return new FolderHarbor({ server: session.server, token: session.token }); } \ No newline at end of file From c098f318d7b9d40312ff3b1e2ca39645e97d6925 Mon Sep 17 00:00:00 2001 From: Nova Date: Mon, 15 Jun 2026 04:14:03 -0600 Subject: [PATCH 3/6] web: migrate user routes, update folderharbor sdk --- web/app/admin/users/[userID]/user.module.tsx | 175 ++++++++----------- web/app/admin/users/create/create.module.tsx | 19 +- web/app/admin/users/users.module.tsx | 17 +- web/package.json | 2 +- web/pnpm-lock.yaml | 20 +-- web/pnpm-workspace.yaml | 2 +- 6 files changed, 105 insertions(+), 130 deletions(-) diff --git a/web/app/admin/users/[userID]/user.module.tsx b/web/app/admin/users/[userID]/user.module.tsx index 877aed5..c9623bf 100644 --- a/web/app/admin/users/[userID]/user.module.tsx +++ b/web/app/admin/users/[userID]/user.module.tsx @@ -1,6 +1,6 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; import { faPlus, faTrash } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -8,12 +8,11 @@ import { isEqual } from "lodash-es"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { Dispatch, SetStateAction, useEffect, useState } from "react"; +import { FHFullUser, FHLimitedUser } from "@folderharbor/sdk"; -type LimitedUser = { access: "limited" | "full", username: string, locked: boolean, failedLogins: number } -type FullUser = LimitedUser & { access: "full", roles: number[], acls: number[], permissions: string[], sessions?: { id: number, createdAt: string, expiry: string }[] } export default function UserSettings({ userID }: { userID: number }) { const [session, setSession] = useState(); - const [user, setUser] = useState(); + const [user, setUser] = useState(); useEffect(() => { async function loadSession() { if (localStorage.getItem("activeSession")) setSession(await db.sessions.get(parseInt(localStorage.getItem("activeSession")!))); } loadSession(); @@ -21,16 +20,13 @@ export default function UserSettings({ userID }: { userID: number }) { useEffect(() => { async function loadUser() { if (!session) return; - const res = await query(session, `admin/users/${userID}`); - if ("error" in res) { - alert(res.error); - return; + try { + setUser(await getClient(session).admin.users.get(userID)); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - setUser(res.body); } loadUser(); }, [session, userID]); @@ -42,74 +38,64 @@ export default function UserSettings({ userID }: { userID: number }) {
); } -function SettingsPanel({ session, user, userID }: { session: Session, user: LimitedUser | FullUser, userID: number }) { +function SettingsPanel({ session, user, userID }: { session: Session, user: FHFullUser | FHLimitedUser, userID: number }) { const router = useRouter(); const [username, setUsername] = useState(user.username); const [password, setPassword] = useState(""); async function updateInfo(e: React.SubmitEvent) { e.preventDefault(); - const res = await query(session, `admin/users/${userID}`, { method: "PATCH", body: JSON.stringify({ username: (username !== user.username ? username : undefined), password: (password !== "" ? password : undefined) }) }); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { - window.location.href = res.redirect; - return; + try { + await getClient(session).admin.users.edit(userID, { username: (username !== user.username ? username : undefined), password: (password !== "" ? password : undefined) }); + alert(`Updated ${username !== user.username ? username : user.username}'s information!${password !== "" ? "\nThey have been signed out across their devices, and will need to log in again." : ""}`); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - alert(`Updated ${username !== user.username ? username : user.username}'s information!${password !== "" ? "\nThey have been signed out across their devices, and will need to log in again." : ""}`); } async function toggleLock() { - const res = await query(session, `admin/users/${userID}/lock`, { method: "PATCH", body: JSON.stringify({ locked: !user.locked }) }); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { - window.location.href = res.redirect; - return; + try { + await getClient(session).admin.users.lock(userID, !user.locked); + window.location.reload(); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - window.location.reload(); } async function deleteUser() { const check = confirm(`Are you sure you want to permanently delete "${user.username}" (ID ${userID}) on "${session.server}"?`); if (!check) return; - const res = await query(session, `admin/users/${userID}`, { method: "DELETE" }); - if ("error" in res) { - alert(res.error); - return; + try { + await getClient(session).admin.users.delete(userID); + router.push("/admin/users"); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - router.push("/admin/users"); } async function revokeSession(id: number) { - const res = await query(session, `admin/sessions/${id}`, { method: "DELETE" }); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { + try { + await getClient(session).admin.revokeSession(id); + window.location.reload(); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); // eslint-disable-next-line react-hooks/immutability - window.location.href = res.redirect; - return; + if ("redirect" in errBody) window.location.href = errBody.redirect; } - window.location.reload(); } async function clearFailedLogins() { - const res = await query(session, `admin/users/${userID}`, { method: "PATCH", body: JSON.stringify({ clearLoginAttempts: true }) }); - if ("error" in res) { - alert(res.error); - return; + try { + await getClient(session).admin.users.edit(userID, { clearFailedLogins: true }); + alert("Successfully reset failed login attempts!"); + window.location.reload(); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - alert("Successfully reset failed login attempts!"); - window.location.reload(); } return (
@@ -144,11 +130,11 @@ function SettingsPanel({ session, user, userID }: { session: Session, user: Limi
} - {user.access === "full" && } + {user.access === "full" && } {user.access === "full" &&

Sessions

- {(user as FullUser).sessions && (user as FullUser).sessions!.map((sessionItem) =>
+ {(user as FHFullUser).sessions && (user as FHFullUser).sessions!.map((sessionItem) =>

Session #{sessionItem.id}

Created {new Date(sessionItem.createdAt).toLocaleString()}

@@ -156,13 +142,13 @@ function SettingsPanel({ session, user, userID }: { session: Session, user: Limi
{session.permissions.includes("users:edit") && }
)} - {(!(user as FullUser).sessions || (user as FullUser).sessions!.length === 0) &&

None

} + {(!(user as FHFullUser).sessions || (user as FHFullUser).sessions!.length === 0) &&

None

}
}
); } -function UserGrants({ session, user, userID }: { session: Session, user: FullUser, userID: number }) { +function UserGrants({ session, user, userID }: { session: Session, user: FHFullUser, userID: number }) { const [roles, setRoles] = useState(user.roles); const [acls, setACLs] = useState(user.acls); const [permissions, setPermissions] = useState(user.permissions); @@ -174,37 +160,32 @@ function UserGrants({ session, user, userID }: { session: Session, user: FullUse let roles; let acls; if (session.permissions.includes("roles:list")) { - roles = await query(session, `admin/roles`); - if ("error" in roles) { - alert(roles.error); - return; - } - if ("redirect" in roles) { - window.location.href = roles.redirect; - return; + try { + roles = await getClient(session).admin.roles.list(); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } } if (session.permissions.includes("acls:list")) { - acls = await query(session, `admin/acls`); - if ("error" in acls) { - alert(acls.error); - return; - } - if ("redirect" in acls) { - window.location.href = acls.redirect; - return; + try { + acls = await getClient(session).admin.acls.list(); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } } - const permissions = await query(session, `admin/permissions`); - if ("error" in permissions) { - alert(permissions.error); - return; + let permissions; + try { + permissions = await getClient(session).admin.permissions(); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in permissions) { - window.location.href = permissions.redirect; - return; - } - setLists({ roles: (roles ? roles.body : undefined), acls: (acls ? acls.body : undefined), permissions: permissions.body }); + setLists({ roles, acls, permissions }); } loadLists(); }, [session]); @@ -219,16 +200,14 @@ function UserGrants({ session, user, userID }: { session: Session, user: FullUse // eslint-disable-next-line @typescript-eslint/no-explicit-any function revokeItem(item: any, state: any[], setState: Dispatch>) { setState(state.filter((current) => current !== item)); } async function applyChanges() { - const res = await query(session, `admin/users/${userID}/grant`, { method: "PUT", body: JSON.stringify({ roles: (!isEqual(roles, user.roles) ? roles : undefined), acls: (!isEqual(acls, user.acls) ? acls : undefined), permissions: (!isEqual(permissions, user.permissions) ? permissions : undefined) }) }); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { - window.location.href = res.redirect; - return; + try { + await getClient(session).admin.users.editGrants(userID, { roles: (!isEqual(roles, user.roles) ? roles : undefined), acls: (!isEqual(acls, user.acls) ? acls : undefined), permissions: (!isEqual(permissions, user.permissions) ? permissions : undefined) }); + alert("Saved new grants successfully!"); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if (res.body.message !== "Nothing to update.") alert("Saved new grants successfully!"); } return (
diff --git a/web/app/admin/users/create/create.module.tsx b/web/app/admin/users/create/create.module.tsx index 409a426..f3ec78c 100644 --- a/web/app/admin/users/create/create.module.tsx +++ b/web/app/admin/users/create/create.module.tsx @@ -1,6 +1,6 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; @@ -16,16 +16,15 @@ export default function CreateUser() { }, []); async function updateInfo(e: React.SubmitEvent) { e.preventDefault(); - const res = await query(session!, `admin/users`, { method: "POST", body: JSON.stringify({ username, password }) }); - if ("error" in res) { - alert(res.error); - return; + let newID; + try { + newID = (await getClient(session!).admin.users.create({ username, password })).id; + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - router.push(`/admin/users/${res.body.id}`); + router.push(`/admin/users/${newID}`); } return (
diff --git a/web/app/admin/users/users.module.tsx b/web/app/admin/users/users.module.tsx index 83bb4d5..5d0daa1 100644 --- a/web/app/admin/users/users.module.tsx +++ b/web/app/admin/users/users.module.tsx @@ -1,6 +1,6 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; import { faPlus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -17,16 +17,13 @@ export default function Users() { useEffect(() => { async function loadUsers() { if (!session) return; - const res = await query(session, "admin/users"); - if ("error" in res) { - alert(res.error); - return; + try { + setUsers(await getClient(session).admin.users.list()); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - setUsers(res.body); } loadUsers(); }, [session]); diff --git a/web/package.json b/web/package.json index 23adfb9..7ad60f4 100644 --- a/web/package.json +++ b/web/package.json @@ -9,7 +9,7 @@ "lint": "eslint" }, "dependencies": { - "@folderharbor/sdk": "^1.1.2", + "@folderharbor/sdk": "^1.1.3", "@fortawesome/fontawesome-svg-core": "^7.2.0", "@fortawesome/free-brands-svg-icons": "^7.2.0", "@fortawesome/free-regular-svg-icons": "^7.2.0", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 31671ba..f2c0425 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@folderharbor/sdk': - specifier: ^1.1.2 - version: 1.1.2 + specifier: ^1.1.3 + version: 1.1.3 '@fortawesome/fontawesome-svg-core': specifier: ^7.2.0 version: 7.2.0 @@ -196,8 +196,8 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@folderharbor/sdk@1.1.2': - resolution: {integrity: sha512-LiK7RoGOf74MAOmGAzkaLUakQ0Vpco9tcvxT5GIGRF1ojl+gQc69fc6mnJ7E+zaDJMygSJeVI58U98eMFg3a3g==} + '@folderharbor/sdk@1.1.3': + resolution: {integrity: sha512-lNZp+9Y20d0nRiVySzsWlc7O7i1Ai5s4KqXAkI6MOzaoTKD4qTlE99Hy0kZXSllxnuR/thjW6U0fnqWboJB+2g==} '@fortawesome/fontawesome-common-types@7.2.0': resolution: {integrity: sha512-IpR0bER9FY25p+e7BmFH25MZKEwFHTfRAfhOyJubgiDnoJNsSvJ7nigLraHtp4VOG/cy8D7uiV0dLkHOne5Fhw==} @@ -2231,7 +2231,7 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 - '@folderharbor/sdk@1.1.2': {} + '@folderharbor/sdk@1.1.3': {} '@fortawesome/fontawesome-common-types@7.2.0': {} @@ -3057,7 +3057,7 @@ snapshots: '@next/eslint-plugin-next': 16.2.6 eslint: 9.39.4(jiti@2.7.0) eslint-import-resolver-node: 0.3.10 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.7.0)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)) eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.4(jiti@2.7.0)) eslint-plugin-react: 7.37.5(eslint@9.39.4(jiti@2.7.0)) @@ -3080,7 +3080,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.7.0)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.3 @@ -3095,14 +3095,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.13.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0)): + eslint-module-utils@2.13.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3) eslint: 9.39.4(jiti@2.7.0) eslint-import-resolver-node: 0.3.10 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.4(jiti@2.7.0)) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)) transitivePeerDependencies: - supports-color @@ -3117,7 +3117,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.39.4(jiti@2.7.0) eslint-import-resolver-node: 0.3.10 - eslint-module-utils: 2.13.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.4(jiti@2.7.0)) + eslint-module-utils: 2.13.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.61.0(eslint@9.39.4(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)))(eslint@9.39.4(jiti@2.7.0)) hasown: 2.0.4 is-core-module: 2.16.2 is-glob: 4.0.3 diff --git a/web/pnpm-workspace.yaml b/web/pnpm-workspace.yaml index 38bd6a9..0e975fe 100644 --- a/web/pnpm-workspace.yaml +++ b/web/pnpm-workspace.yaml @@ -5,4 +5,4 @@ ignoredBuiltDependencies: - sharp - unrs-resolver minimumReleaseAgeExclude: - - '@folderharbor/sdk@1.1.2' + - '@folderharbor/sdk@1.1.3' From 6b093644f4ea667bd61287becb7c471810468b5f Mon Sep 17 00:00:00 2001 From: Nova Date: Mon, 15 Jun 2026 05:01:53 -0600 Subject: [PATCH 4/6] web: add sdk methods for roles --- web/app/admin/roles/[roleID]/role.module.tsx | 104 ++++++++----------- web/app/admin/roles/create/create.module.tsx | 18 ++-- web/app/admin/roles/roles.module.tsx | 17 ++- 3 files changed, 61 insertions(+), 78 deletions(-) diff --git a/web/app/admin/roles/[roleID]/role.module.tsx b/web/app/admin/roles/[roleID]/role.module.tsx index 6d86766..bfad858 100644 --- a/web/app/admin/roles/[roleID]/role.module.tsx +++ b/web/app/admin/roles/[roleID]/role.module.tsx @@ -1,7 +1,8 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; +import { FHRole } from "@folderharbor/sdk"; import { faPlus, faTrash } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { isEqual } from "lodash-es"; @@ -9,10 +10,9 @@ import Link from "next/link"; import { useRouter } from "next/navigation"; import { Dispatch, SetStateAction, useEffect, useState } from "react"; -type Role = { name: string, acls: number[], permissions: string[] } export default function RoleSettings({ roleID }: { roleID: number }) { const [session, setSession] = useState(); - const [role, setRole] = useState(); + const [role, setRole] = useState(); useEffect(() => { async function loadSession() { if (localStorage.getItem("activeSession")) setSession(await db.sessions.get(parseInt(localStorage.getItem("activeSession")!))); } loadSession(); @@ -20,16 +20,13 @@ export default function RoleSettings({ roleID }: { roleID: number }) { useEffect(() => { async function loadRole() { if (!session) return; - const res = await query(session, `admin/roles/${roleID}`); - if ("error" in res) { - alert(res.error); - return; + try { + setRole(await getClient(session).admin.roles.get(roleID)); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - setRole(res.body); } loadRole(); }, [session, roleID]); @@ -41,34 +38,30 @@ export default function RoleSettings({ roleID }: { roleID: number }) {
); } -function SettingsPanel({ session, role, roleID }: { session: Session, role: Role, roleID: number }) { +function SettingsPanel({ session, role, roleID }: { session: Session, role: FHRole, roleID: number }) { const router = useRouter(); const [name, setName] = useState(role.name); async function updateInfo(e: React.SubmitEvent) { e.preventDefault(); - const res = await query(session, `admin/roles/${roleID}`, { method: "PATCH", body: JSON.stringify({ name: (name !== role.name ? name : undefined) }) }); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } + try { + await getClient(session).admin.roles.edit(roleID, { name: (name !== role.name ? name : undefined) }); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; + } alert(`Updated ${name !== role.name ? name : role.name}'s information!`); } async function deleteRole() { const check = confirm(`Are you sure you want to permanently delete the role "${role.name}" (ID ${roleID}) on "${session.server}"?`); if (!check) return; - const res = await query(session, `admin/roles/${roleID}`, { method: "DELETE" }); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } + try { + await getClient(session).admin.roles.delete(roleID); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; + } router.push("/admin/roles"); } return ( @@ -96,7 +89,7 @@ function SettingsPanel({ session, role, roleID }: { session: Session, role: Role ); } -function RoleGrants({ session, role, roleID }: { session: Session, role: Role, roleID: number }) { +function RoleGrants({ session, role, roleID }: { session: Session, role: FHRole, roleID: number }) { const [acls, setACLs] = useState(role.acls); const [permissions, setPermissions] = useState(role.permissions); const [newGrant, setNewGrant] = useState<{ acl: string, permission: string }>({ acl: "", permission: "" }); @@ -106,26 +99,23 @@ function RoleGrants({ session, role, roleID }: { session: Session, role: Role, r if (!session) return; let acls; if (session.permissions.includes("acls:list")) { - acls = await query(session, `admin/acls`); - if ("error" in acls) { - alert(acls.error); - return; - } - if ("redirect" in acls) { - window.location.href = acls.redirect; - return; + try { + acls = await getClient(session).admin.acls.list(); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } } - const permissions = await query(session, `admin/permissions`); - if ("error" in permissions) { - alert(permissions.error); - return; + let permissions; + try { + permissions = await getClient(session).admin.permissions(); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in permissions) { - window.location.href = permissions.redirect; - return; - } - setLists({ acls: (acls ? acls.body : undefined), permissions: permissions.body }); + setLists({ acls, permissions }); } loadLists(); }, [session]); @@ -140,16 +130,14 @@ function RoleGrants({ session, role, roleID }: { session: Session, role: Role, r // eslint-disable-next-line @typescript-eslint/no-explicit-any function revokeItem(item: any, state: any[], setState: Dispatch>) { setState(state.filter((current) => current !== item)); } async function applyChanges() { - const res = await query(session, `admin/roles/${roleID}`, { method: "PATCH", body: JSON.stringify({ acls: (!isEqual(acls, role.acls) ? acls : undefined), permissions: (!isEqual(permissions, role.permissions) ? permissions : undefined) }) }); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { - window.location.href = res.redirect; - return; + try { + await getClient(session).admin.roles.edit(roleID, { acls: (!isEqual(acls, role.acls) ? acls : undefined), permissions: (!isEqual(permissions, role.permissions) ? permissions : undefined) }); + alert("Saved new grants successfully!"); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if (res.body.message !== "Nothing to update.") alert("Saved new grants successfully!"); } return (
diff --git a/web/app/admin/roles/create/create.module.tsx b/web/app/admin/roles/create/create.module.tsx index 0361ee7..88a14c5 100644 --- a/web/app/admin/roles/create/create.module.tsx +++ b/web/app/admin/roles/create/create.module.tsx @@ -1,6 +1,6 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; @@ -15,16 +15,14 @@ export default function CreateRole() { }, []); async function updateInfo(e: React.SubmitEvent) { e.preventDefault(); - const res = await query(session!, `admin/roles`, { method: "POST", body: JSON.stringify({ name }) }); - if ("error" in res) { - alert(res.error); - return; + try { + const role = await getClient(session!).admin.roles.create({ name }); + router.push(`/admin/roles/${role.id}`); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - router.push(`/admin/roles/${res.body.id}`); } return ( diff --git a/web/app/admin/roles/roles.module.tsx b/web/app/admin/roles/roles.module.tsx index a34f959..86c1336 100644 --- a/web/app/admin/roles/roles.module.tsx +++ b/web/app/admin/roles/roles.module.tsx @@ -1,6 +1,6 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; import { faPlus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -17,16 +17,13 @@ export default function Roles() { useEffect(() => { async function loadRoles() { if (!session) return; - const res = await query(session, "admin/roles"); - if ("error" in res) { - alert(res.error); - return; + try { + setRoles(await getClient(session).admin.roles.list()); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - setRoles(res.body); } loadRoles(); }, [session]); From 468cc1ea9dd175586bb2478102ece2da27a07a8e Mon Sep 17 00:00:00 2001 From: Nova Date: Mon, 15 Jun 2026 05:33:09 -0600 Subject: [PATCH 5/6] web: add sdk methods to acls and config, update sdk version --- web/app/admin/acls/[aclID]/acl.module.tsx | 65 +++++++++----------- web/app/admin/acls/acls.module.tsx | 17 +++-- web/app/admin/acls/create/create.module.tsx | 18 +++--- web/app/admin/config/config.module.tsx | 17 +++-- web/app/admin/users/[userID]/user.module.tsx | 2 +- web/package.json | 2 +- web/pnpm-lock.yaml | 10 +-- web/pnpm-workspace.yaml | 2 +- 8 files changed, 58 insertions(+), 75 deletions(-) diff --git a/web/app/admin/acls/[aclID]/acl.module.tsx b/web/app/admin/acls/[aclID]/acl.module.tsx index 7a6f6c5..cb95056 100644 --- a/web/app/admin/acls/[aclID]/acl.module.tsx +++ b/web/app/admin/acls/[aclID]/acl.module.tsx @@ -1,6 +1,6 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; import { faPlus, faTrash } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -19,16 +19,13 @@ export default function ACLSettings({ aclID }: { aclID: number }) { useEffect(() => { async function loadACL() { if (!session) return; - const res = await query(session, `admin/acls/${aclID}`); - if ("error" in res) { - alert(res.error); - return; + try { + setACL(await getClient(session).admin.acls.get(aclID)); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - setACL(res.body); } loadACL(); }, [session, aclID]); @@ -45,30 +42,26 @@ function SettingsPanel({ session, acl, aclID }: { session: Session, acl: ACL, ac const [name, setName] = useState(acl.name); async function updateInfo(e: React.SubmitEvent) { e.preventDefault(); - const res = await query(session, `admin/acls/${aclID}`, { method: "PATCH", body: JSON.stringify({ name: (name !== acl.name ? name : undefined) }) }); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { - window.location.href = res.redirect; - return; + try { + await getClient(session).admin.acls.edit(aclID, { name: (name !== acl.name ? name : undefined) }); + alert(`Updated ${name !== acl.name ? name : acl.name}'s information!`); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - alert(`Updated ${name !== acl.name ? name : acl.name}'s information!`); } async function deleteACL() { const check = confirm(`Are you sure you want to permanently delete the ACL "${acl.name}" (ID ${aclID}) on "${session.server}"?`); if (!check) return; - const res = await query(session, `admin/acls/${aclID}`, { method: "DELETE" }); - if ("error" in res) { - alert(res.error); - return; + try { + await getClient(session).admin.acls.delete(aclID); + router.push("/admin/acls"); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - router.push("/admin/acls"); } return (
@@ -108,16 +101,14 @@ function ACLPaths({ session, acl, aclID }: { session: Session, acl: ACL, aclID: } function removePath(item: string, state: string[], setState: Dispatch>) { setState(state.filter((current) => current !== item)); } async function applyChanges() { - const res = await query(session, `admin/acls/${aclID}`, { method: "PATCH", body: JSON.stringify({ allow: (!isEqual(allow, acl.allow) ? allow : undefined), deny: (!isEqual(deny, acl.deny) ? deny : undefined) }) }); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { - window.location.href = res.redirect; - return; + try { + await getClient(session).admin.acls.edit(aclID, { allow: (!isEqual(allow, acl.allow) ? allow : undefined), deny: (!isEqual(deny, acl.deny) ? deny : undefined) }); + alert("Saved new paths successfully!"); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if (res.body.message !== "Nothing to update.") alert("Saved new paths successfully!"); } return (
diff --git a/web/app/admin/acls/acls.module.tsx b/web/app/admin/acls/acls.module.tsx index 5398500..d761e84 100644 --- a/web/app/admin/acls/acls.module.tsx +++ b/web/app/admin/acls/acls.module.tsx @@ -1,6 +1,6 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; import { faPlus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -17,16 +17,13 @@ export default function ACLs() { useEffect(() => { async function loadACLs() { if (!session) return; - const res = await query(session, "admin/acls"); - if ("error" in res) { - alert(res.error); - return; + try { + setACLs(await getClient(session).admin.acls.list()); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - setACLs(res.body); } loadACLs(); }, [session]); diff --git a/web/app/admin/acls/create/create.module.tsx b/web/app/admin/acls/create/create.module.tsx index 1c7fcfc..a1009a1 100644 --- a/web/app/admin/acls/create/create.module.tsx +++ b/web/app/admin/acls/create/create.module.tsx @@ -1,6 +1,6 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; @@ -15,16 +15,14 @@ export default function CreateACL() { }, []); async function updateInfo(e: React.SubmitEvent) { e.preventDefault(); - const res = await query(session!, `admin/acls`, { method: "POST", body: JSON.stringify({ name }) }); - if ("error" in res) { - alert(res.error); - return; + try { + const acl = await getClient(session!).admin.acls.create({ name }); + router.push(`/admin/acls/${acl.id}`); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - router.push(`/admin/acls/${res.body.id}`); } return ( diff --git a/web/app/admin/config/config.module.tsx b/web/app/admin/config/config.module.tsx index 67c7acf..c5159d9 100644 --- a/web/app/admin/config/config.module.tsx +++ b/web/app/admin/config/config.module.tsx @@ -1,6 +1,6 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; import { useEffect, useState } from "react"; @@ -14,16 +14,13 @@ export default function Config() { useEffect(() => { async function loadConfig() { if (!session) return; - const res = await query(session, `admin/config`); - if ("error" in res) { - alert(res.error); - return; + try { + setConfig(await getClient(session).admin.config.read()); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - setConfig(res.body); } loadConfig(); }, [session]); diff --git a/web/app/admin/users/[userID]/user.module.tsx b/web/app/admin/users/[userID]/user.module.tsx index c9623bf..4657c46 100644 --- a/web/app/admin/users/[userID]/user.module.tsx +++ b/web/app/admin/users/[userID]/user.module.tsx @@ -88,7 +88,7 @@ function SettingsPanel({ session, user, userID }: { session: Session, user: FHFu } async function clearFailedLogins() { try { - await getClient(session).admin.users.edit(userID, { clearFailedLogins: true }); + await getClient(session).admin.users.edit(userID, { clearLoginAttempts: true }); alert("Successfully reset failed login attempts!"); window.location.reload(); } catch (e) { diff --git a/web/package.json b/web/package.json index 7ad60f4..c3afeee 100644 --- a/web/package.json +++ b/web/package.json @@ -9,7 +9,7 @@ "lint": "eslint" }, "dependencies": { - "@folderharbor/sdk": "^1.1.3", + "@folderharbor/sdk": "^1.1.4", "@fortawesome/fontawesome-svg-core": "^7.2.0", "@fortawesome/free-brands-svg-icons": "^7.2.0", "@fortawesome/free-regular-svg-icons": "^7.2.0", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index f2c0425..d5597a6 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@folderharbor/sdk': - specifier: ^1.1.3 - version: 1.1.3 + specifier: ^1.1.4 + version: 1.1.4 '@fortawesome/fontawesome-svg-core': specifier: ^7.2.0 version: 7.2.0 @@ -196,8 +196,8 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@folderharbor/sdk@1.1.3': - resolution: {integrity: sha512-lNZp+9Y20d0nRiVySzsWlc7O7i1Ai5s4KqXAkI6MOzaoTKD4qTlE99Hy0kZXSllxnuR/thjW6U0fnqWboJB+2g==} + '@folderharbor/sdk@1.1.4': + resolution: {integrity: sha512-KlAl4On/5copXZmTDEVLX5DoNHXFho0RyQFwy6SXc1hrGngMlfv0jqfxmbPCuzWK4hRLo+ecWVI3FOtCAYo2qg==} '@fortawesome/fontawesome-common-types@7.2.0': resolution: {integrity: sha512-IpR0bER9FY25p+e7BmFH25MZKEwFHTfRAfhOyJubgiDnoJNsSvJ7nigLraHtp4VOG/cy8D7uiV0dLkHOne5Fhw==} @@ -2231,7 +2231,7 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 - '@folderharbor/sdk@1.1.3': {} + '@folderharbor/sdk@1.1.4': {} '@fortawesome/fontawesome-common-types@7.2.0': {} diff --git a/web/pnpm-workspace.yaml b/web/pnpm-workspace.yaml index 0e975fe..389cf98 100644 --- a/web/pnpm-workspace.yaml +++ b/web/pnpm-workspace.yaml @@ -5,4 +5,4 @@ ignoredBuiltDependencies: - sharp - unrs-resolver minimumReleaseAgeExclude: - - '@folderharbor/sdk@1.1.3' + - '@folderharbor/sdk@1.1.4' From 97bc6138d3550c976d671cc3cb4494297a70fd39 Mon Sep 17 00:00:00 2001 From: Nova Date: Mon, 15 Jun 2026 05:50:39 -0600 Subject: [PATCH 6/6] web: migrate to sdk for logs, permissions, and user settings --- web/app/admin/tools/logs/logs.module.tsx | 24 ++-- .../tools/permissions/permissions.module.tsx | 17 ++- web/app/settings/settings.module.tsx | 106 ++++++++---------- web/folderharborweb.d.ts | 4 - 4 files changed, 65 insertions(+), 86 deletions(-) diff --git a/web/app/admin/tools/logs/logs.module.tsx b/web/app/admin/tools/logs/logs.module.tsx index 3ff455f..ebd887f 100644 --- a/web/app/admin/tools/logs/logs.module.tsx +++ b/web/app/admin/tools/logs/logs.module.tsx @@ -1,6 +1,6 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; import { faArrowLeft, faArrowRight } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -9,7 +9,7 @@ import { useEffect, useState } from "react"; export default function Logs() { const [session, setSession] = useState(); // eslint-disable-next-line @typescript-eslint/no-explicit-any - const [logs, setLogs] = useState<{ userID: number, username: string | null, action: string, body: any | null, blurb: string, createdAt: string }[] | undefined>(); + const [logs, setLogs] = useState<{ userID: number, username: string | null, action: string, body: any | null, blurb: string, createdAt: Date }[] | undefined>(); const [page, setPage] = useState(1); const [pageCount, setPageCount] = useState(1); useEffect(() => { @@ -19,24 +19,22 @@ export default function Logs() { useEffect(() => { async function loadLogs() { if (!session) return; - const res = await query(session, `admin/logs?page=${page}`); - if ("error" in res) { - alert(res.error); - return; + try { + const logs = await getClient(session).admin.logs(page); + setLogs(logs.logs); + setPageCount(logs.pageCount); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - setLogs(res.body.logs); - setPageCount(res.body.pageCount); } loadLogs(); }, [session, page]); return (
{(session && logs) &&
- {logs.map((entry) =>
+ {logs.map((entry) =>

{entry.username}

(ID #{entry.userID}) {entry.blurb} at {new Date(entry.createdAt).toLocaleString()} ({entry.action})
{entry.body &&
{JSON.stringify(entry.body, null, 2)}
}
)} diff --git a/web/app/admin/tools/permissions/permissions.module.tsx b/web/app/admin/tools/permissions/permissions.module.tsx index 660f339..9aebf2a 100644 --- a/web/app/admin/tools/permissions/permissions.module.tsx +++ b/web/app/admin/tools/permissions/permissions.module.tsx @@ -1,6 +1,6 @@ "use client" import { Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; import { useEffect, useState } from "react"; @@ -14,16 +14,13 @@ export default function Permissions() { useEffect(() => { async function loadPermissions() { if (!session) return; - const res = await query(session, `admin/permissions`); - if ("error" in res) { - alert(res.error); - return; + try { + setPermissions(await getClient(session).admin.permissions()); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - setPermissions(res.body); } loadPermissions(); }, [session]); diff --git a/web/app/settings/settings.module.tsx b/web/app/settings/settings.module.tsx index 25b568b..5e35280 100644 --- a/web/app/settings/settings.module.tsx +++ b/web/app/settings/settings.module.tsx @@ -1,17 +1,17 @@ "use client" -import { ClientConfig, Session } from "@/folderharborweb"; -import query from "@/utils/api"; +import { Session } from "@/folderharborweb"; +import { getClient, handleError } from "@/utils/api"; import { db } from "@/utils/db"; +import { FHClientConfig, FHSelfInfo } from "@folderharbor/sdk"; import { faLock, faTrash } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useRouter } from "next/navigation"; import { useEffect, useState } from "react"; -type SelfInfo = { id: number, username: string, sessions: { id: number, createdAt: string, expiry: string }[], activeSession: number, failedLoginLockout: boolean, permissions: string[] }; export default function Settings() { const [session, setSession] = useState(); - const [selfInfo, setSelfInfo] = useState(); - const [clientConfig, setClientConfig] = useState(); + const [selfInfo, setSelfInfo] = useState(); + const [clientConfig, setClientConfig] = useState(); useEffect(() => { async function loadSession() { if (localStorage.getItem("activeSession")) setSession(await db.sessions.get(parseInt(localStorage.getItem("activeSession")!))); } loadSession(); @@ -19,29 +19,23 @@ export default function Settings() { useEffect(() => { async function loadSelfInfo() { if (!session) return; - const res = await query(session, "me"); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { - window.location.href = res.redirect; - return; + try { + setSelfInfo(await getClient(session).me.info()); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - setSelfInfo(res.body); } async function loadClientConfig() { if (!session) return; - const res = await query(session, "clientconfig"); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { - window.location.href = res.redirect; - return; + try { + setClientConfig(await getClient(session).clientconfig()); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - setClientConfig({ selfUsernameChanges: res.body.selfUsernameChanges, registration: res.body.registration }); } loadSelfInfo(); loadClientConfig(); @@ -53,55 +47,49 @@ export default function Settings() {
); } -function SettingsForm({ session, selfInfo, clientConfig }: { session: Session, selfInfo: SelfInfo, clientConfig: ClientConfig }) { +function SettingsForm({ session, selfInfo, clientConfig }: { session: Session, selfInfo: FHSelfInfo, clientConfig: FHClientConfig }) { const router = useRouter(); const [username, setUsername] = useState(selfInfo.username); const [password, setPassword] = useState(""); async function clearFailedLogins() { - const res = await query(session, "me", { method: "PATCH", body: JSON.stringify({ clearLoginAttempts: true }) }); - if ("error" in res) { - alert(res.error); - return; + try { + await getClient(session).me.edit({ clearLoginAttempts: true }); + alert("Successfully reset failed login attempts!"); + window.location.reload(); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - alert("Successfully reset failed login attempts!"); - window.location.reload(); } async function revokeSession(id: number) { - const res = await query(session, "me/session", { method: "DELETE", body: JSON.stringify({ sessionID: id }) }); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { + try { + await getClient(session).me.revokeSession(id); + window.location.reload(); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); // eslint-disable-next-line react-hooks/immutability - window.location.href = res.redirect; - return; + if ("redirect" in errBody) window.location.href = errBody.redirect; } - window.location.reload(); } async function updateInfo(e: React.SubmitEvent) { e.preventDefault(); - const res = await query(session, "me", { method: "PATCH", body: JSON.stringify({ username: (username !== selfInfo.username ? username : undefined), password: (password !== "" ? password : undefined) }) }); - if ("error" in res) { - alert(res.error); - return; - } - if ("redirect" in res) { - window.location.href = res.redirect; - return; - } - alert(`Updated your info successfully!${password !== "" ? `\nYou have been signed out of all sessions, and will need to log in again.\nAs a reminder, your server address is "${session.server}", and your username is "${username !== selfInfo.username ? username : selfInfo.username}".` : ""}`); - if (password !== "") { - db.sessions.delete(parseInt(localStorage.getItem("activeSession")!)); - localStorage.removeItem("activeSession"); - router.push("/"); - return; + try { + await getClient(session).me.edit({ username: (username !== selfInfo.username ? username : undefined), password: (password !== "" ? password : undefined) }); + alert(`Updated your info successfully!${password !== "" ? `\nYou have been signed out of all sessions, and will need to log in again.\nAs a reminder, your server address is "${session.server}", and your username is "${username !== selfInfo.username ? username : selfInfo.username}".` : ""}`); + if (password !== "") { + db.sessions.delete(parseInt(localStorage.getItem("activeSession")!)); + localStorage.removeItem("activeSession"); + router.push("/"); + return; + } + if (username !== selfInfo.username) db.sessions.update(parseInt(localStorage.getItem("activeSession")!), { username: username }); + } catch (e) { + const errBody = handleError(e as Error); + if ("error" in errBody) alert(errBody.error); + if ("redirect" in errBody) window.location.href = errBody.redirect; } - if (username !== selfInfo.username) db.sessions.update(parseInt(localStorage.getItem("activeSession")!), { username: username }); } return (
= 1 ? "md:grid-cols-3" : "md:grid-cols-2"} gap-4 md:gap-2 my-4`}> diff --git a/web/folderharborweb.d.ts b/web/folderharborweb.d.ts index 209d7d5..e54d77a 100644 --- a/web/folderharborweb.d.ts +++ b/web/folderharborweb.d.ts @@ -4,8 +4,4 @@ export type Session = { token: string username: string permissions: string[] -} -export type ClientConfig = { - selfUsernameChanges: boolean - registration: boolean } \ No newline at end of file