From 63e510c2dc29d61349ec9ac141f2ac61c48719e9 Mon Sep 17 00:00:00 2001 From: Bailey Pumfleet Date: Thu, 29 Oct 2026 15:36:56 -0500 Subject: [PATCH 1/4] refactor(app): share session state, screen and transcript reading in packages/core The phone app will read sessions, screens, transcripts and pairing links the way the desktop app does. packages/core holds that code as plain TypeScript with only relative imports and no DOM, so Vite, Metro and node's test runner load it as it is. app/src/lib re-exports each file, so nothing in the app changes. check:core keeps the package to itself. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 5 +- AGENTS.md | 5 +- app/package.json | 3 +- app/scripts/check-core.mjs | 41 ++++ app/src/lib/conversation-store.ts | 32 +-- app/src/lib/derive.ts | 217 +----------------- app/src/lib/format.ts | 26 +-- app/src/lib/net.ts | 98 +------- app/src/lib/phone.ts | 16 +- app/src/lib/questions.ts | 98 +------- app/src/lib/screen.ts | 147 +----------- app/src/lib/state-model.ts | 39 +--- app/src/lib/transcript.ts | 204 +--------------- app/vite.config.ts | 2 +- packages/core/README.md | 16 ++ packages/core/package.json | 7 + packages/core/src/conversation.ts | 46 ++++ .../lib => packages/core/src}/derive.test.ts | 4 +- packages/core/src/derive.ts | 215 +++++++++++++++++ packages/core/src/format.ts | 24 ++ .../src/lib => packages/core/src}/net.test.ts | 2 +- packages/core/src/net.ts | 96 ++++++++ packages/core/src/pairing.test.ts | 52 +++++ packages/core/src/pairing.ts | 111 +++++++++ .../core/src}/questions.test.ts | 2 +- packages/core/src/questions.ts | 95 ++++++++ .../lib => packages/core/src}/screen.test.ts | 2 +- packages/core/src/screen.ts | 145 ++++++++++++ packages/core/src/state.ts | 41 ++++ packages/core/src/transcript.ts | 202 ++++++++++++++++ packages/core/tsconfig.json | 21 ++ 31 files changed, 1151 insertions(+), 863 deletions(-) create mode 100644 app/scripts/check-core.mjs create mode 100644 packages/core/README.md create mode 100644 packages/core/package.json create mode 100644 packages/core/src/conversation.ts rename {app/src/lib => packages/core/src}/derive.test.ts (97%) create mode 100644 packages/core/src/derive.ts create mode 100644 packages/core/src/format.ts rename {app/src/lib => packages/core/src}/net.test.ts (97%) create mode 100644 packages/core/src/net.ts create mode 100644 packages/core/src/pairing.test.ts create mode 100644 packages/core/src/pairing.ts rename {app/src/lib => packages/core/src}/questions.test.ts (97%) create mode 100644 packages/core/src/questions.ts rename {app/src/lib => packages/core/src}/screen.test.ts (98%) create mode 100644 packages/core/src/screen.ts create mode 100644 packages/core/src/state.ts create mode 100644 packages/core/src/transcript.ts create mode 100644 packages/core/tsconfig.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28e1b1495..33feaaeee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -149,7 +149,10 @@ jobs: # Every built-in theme's text, states and terminal meet their contrast # (src/themes/contrast.ts). - run: pnpm check:themes - # The split tree's moves (lib/layout.test.ts). + # packages/core, shared with the phone app, imports only itself and + # has no DOM (scripts/check-core.mjs). + - run: pnpm check:core + # The split tree's moves (lib/layout.test.ts), and packages/core's tests. - run: pnpm test - run: pnpm build # The smoke suite (e2e/): the production build in Playwright's Chromium, diff --git a/AGENTS.md b/AGENTS.md index e50f6efac..4cc09f3f2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,6 +5,7 @@ Shipyard (formerly Berth) runs coding agents on your own machines. This repo has - `cmd/berthd`, `internal/box`: the box daemon. It runs agents, terminals and services in its own tmux server. - `cmd/berth`, `internal/agent`: the laptop CLI and agent (UI API on 1378, proxy on 1377, phone on 1379). - `app/`: the Tauri 2 + React desktop app (coss-ui, 23 themes). `app/e2e` holds the Playwright suite on mock fixtures. +- `packages/core`: plain TypeScript shared by `app/` and the phone app (session state, screen and transcript reading, pairing links). Only relative `./x.ts` imports and the plugin SDK's types; no DOM (`check:core`). `app/src/lib/.ts` re-exports it. - `docs/`: the docs as MDX, built by `docs-site/` (Fumadocs). `site/` is the landing page and `install.sh`. **Names:** "Shipyard" is the brand in everything people read. `berth`, `berthd`, `~/.berth`, `BERTH_*`, `berth://`, `dev.berth.app`, `berth.prefs` and the `berth-*` skill ids are identifiers. Don't rename them; a later change will, with migrations. @@ -17,7 +18,7 @@ Run these before you call something done: go vet ./... && go test -race ./... # -race: CI runs it, and it has caught real races (cd app/src-tauri && cargo check) cd app && CI=true pnpm install --frozen-lockfile -pnpm typecheck:plugins && pnpm check:titles && pnpm check:type && pnpm check:grid && pnpm check:csp && pnpm check:themes && pnpm test && pnpm build +pnpm typecheck:plugins && pnpm check:titles && pnpm check:type && pnpm check:grid && pnpm check:csp && pnpm check:themes && pnpm check:core && pnpm test && pnpm build npx tsc -p e2e (cd docs-site && pnpm build) # when docs/ changed ``` @@ -29,7 +30,7 @@ Browser tests: run the specs you touched, not the whole suite (`E2E_PORT=14xx np - **Ports:** 1420 is the dev app and 1377–1379 the laptop agent: never use or kill them. Vite and Playwright use `E2E_PORT` in 1421–1439, and you check the port is free first. - **Hands off:** never touch `~/.berth`, `~/Library/Application Support/berth` or the `dev.berth.berthd` launchd job. Kill only PIDs you started; no `pkill node`/`vite`/`next-server`. - **No symlinked `node_modules`** (pnpm breaks without a TTY). Install per worktree. -- **New unit test files** go in `app/src/lib/` as `*.test.ts`; `pnpm test` finds them there (`src/lib/**/*.test.ts`). Don't list them in `package.json`. +- **New unit test files** go in `app/src/lib/` (or `packages/core/src/` beside shared code) as `*.test.ts`; `pnpm test` finds them there. Don't list them in `package.json`. - **No `title=` attributes** in the app (`check:titles`); use ``. - **Layout grid** (`check:grid`, "The layout grid" in `app/src/index.css`): a top band is `h-bar`, a pane's toolbar `h-bar-pane`; boxes start on `px-edge`, their content on `pl-lane`, a full page on `px-page`. No raw pixel gutters (`pl-[11px]`); a deliberate exception gets a `grid-ok: why` comment. - **Text sizes come from the type scale** (`text-body`, `text-desc`, `text-meta`, `text-tag`, … in `index.css`), never `text-sm` or `text-[11px]` (`check:type`). coss ui's own parts in `components/ui` keep theirs. diff --git a/app/package.json b/app/package.json index 5f94642dd..37096f50e 100644 --- a/app/package.json +++ b/app/package.json @@ -18,6 +18,7 @@ "check:grid": "node scripts/check-grid.mjs", "check:plugin-consent": "node scripts/check-plugin-consent.mjs", "check:csp": "node scripts/check-csp.mjs", + "check:core": "node scripts/check-core.mjs && tsc -p ../packages/core", "check:themes": "node --experimental-strip-types --test src/themes/contrast.test.ts", "test:e2e": "tsc --noEmit -p e2e && pnpm -s build && playwright test", "smoke:live": "node e2e/live.mjs", @@ -25,7 +26,7 @@ "perf:guard": "node perf/guard.mjs", "perf:soak": "node perf/soak.mjs", "perf:terminals": "node perf/terminals.mjs", - "test": "node --experimental-strip-types --test 'src/lib/**/*.test.ts'" + "test": "node --experimental-strip-types --test 'src/lib/**/*.test.ts' '../packages/core/src/**/*.test.ts'" }, "dependencies": { "@base-ui/react": "^1.8.0", diff --git a/app/scripts/check-core.mjs b/app/scripts/check-core.mjs new file mode 100644 index 000000000..130a6cc6e --- /dev/null +++ b/app/scripts/check-core.mjs @@ -0,0 +1,41 @@ +// Fails when packages/core reaches past itself: an import of a package, an +// alias (@/lib/…), a path without its .ts extension, or the DOM. +// +// The desktop app (Vite), the phone app (Metro) and node's test runner all +// load packages/core's files as they are, so each may import only its +// neighbours by a relative path with .ts, plus types from the plugin SDK. +// tsc -p ../packages/core (in check:core, after this) checks the rest: +// that lib has no DOM. +// +// node scripts/check-core.mjs +import { readdir, readFile } from "node:fs/promises"; +import { join, relative, resolve } from "node:path"; + +const app = resolve(import.meta.dirname, ".."); +const core = resolve(app, "..", "packages", "core", "src"); +const SDK = "../../plugin-sdk/src/types.ts"; + +const problems = []; +for (const name of (await readdir(core, { recursive: true })).filter((n) => n.endsWith(".ts"))) { + const file = join(core, name); + const test = name.endsWith(".test.ts"); + const src = await readFile(file, "utf8"); + for (const m of src.matchAll(/^\s*(import|export)\s+(type\s+)?[^;]*?\sfrom\s+"([^"]+)"/gms)) { + const [, , type, spec] = m; + const line = src.slice(0, m.index).split("\n").length + (m[0].match(/^\s*/)[0].split("\n").length - 1); + const where = `${relative(resolve(app, ".."), file)}:${line}`; + if (test && spec.startsWith("node:")) continue; + if (spec === SDK) { + if (!type) problems.push(`${where}: import only types from the plugin SDK (import type …)`); + continue; + } + if (!spec.startsWith("./")) problems.push(`${where}: "${spec}" is outside packages/core; import a neighbour by ./name.ts`); + else if (!spec.endsWith(".ts")) problems.push(`${where}: "${spec}" needs its .ts extension`); + } +} + +if (problems.length) { + console.error(`packages/core may only import its own files (./x.ts) and the plugin SDK's types:\n\n${problems.join("\n")}`); + process.exit(1); +} +console.log("check:core: packages/core imports only itself"); diff --git a/app/src/lib/conversation-store.ts b/app/src/lib/conversation-store.ts index 033d00918..6ddffb3db 100644 --- a/app/src/lib/conversation-store.ts +++ b/app/src/lib/conversation-store.ts @@ -1,6 +1,7 @@ import { create } from "zustand"; import type { Artifact, CrewMember, TranscriptItem } from "@/lib/transcript"; +import { fillItems, mergeItems, offOf, resyncItems } from "../../../packages/core/src/conversation.ts"; // The conversations the app holds for agents shown as a conversation rather // than a terminal: each session's recent items and the crew working beside @@ -34,9 +35,7 @@ interface ConversationState { setArtifacts(key: string, list: Artifact[]): void; } -// Where an item's line starts in the agent's record (boxes send it as off; -// 0 is left out). -export const offOf = (it: TranscriptItem) => (it as { off?: number }).off ?? 0; +export { offOf }; // spill hears the items a chat lets go past KEEP, oldest first: the chat's // older turns (lib/history) take them, so what it shows has no hole. @@ -56,30 +55,11 @@ export const useConversations = create()((set, get) => { crew: {}, artifacts: {}, push: (key, item) => put(key, [...(get().items[key] ?? []), item]), - merge: (key, incoming) => { - const list = [...(get().items[key] ?? [])]; - const at = new Map(list.map((it, i) => [it.id, i])); - for (const it of incoming) { - const i = at.get(it.id); - if (i === undefined) { - at.set(it.id, list.length); - list.push(it); - } else list[i] = it; - } - put(key, list); - }, - resync: (key, window, start, fresh) => { - const held = fresh ? [] : (get().items[key] ?? []).filter((it) => offOf(it) < start); - const ids = new Set(window.map((it) => it.id)); - put(key, [...held.filter((it) => !ids.has(it.id)), ...window]); - }, + merge: (key, incoming) => put(key, mergeItems(get().items[key] ?? [], incoming)), + resync: (key, window, start, fresh) => put(key, resyncItems(get().items[key] ?? [], window, start, fresh)), fill: (key, items) => { - const list = get().items[key] ?? []; - const have = new Set(list.map((it) => it.id)); - const add = items.filter((it) => !have.has(it.id)); - if (!add.length) return; - // In the record's order; a sort that keeps the order of equals. - put(key, [...list, ...add].map((it, i) => [it, i] as const).sort((a, b) => offOf(a[0]) - offOf(b[0]) || a[1] - b[1]).map(([it]) => it)); + const list = fillItems(get().items[key] ?? [], items); + if (list) put(key, list); }, update: (key, id, patch) => set((s) => ({ items: { ...s.items, [key]: (s.items[key] ?? []).map((i) => (i.id === id ? ({ ...i, ...patch } as TranscriptItem) : i)) } })), diff --git a/app/src/lib/derive.ts b/app/src/lib/derive.ts index ef288b902..42a36ec32 100644 --- a/app/src/lib/derive.ts +++ b/app/src/lib/derive.ts @@ -1,215 +1,2 @@ -import type { Location, Session, Stats, Worktree } from "@/lib/api"; - -// What the app shows for a session: the agent's last reported state ("ready" -// is an agent open with nothing to do yet), "exited" once the program ended, -// or "idle" for a plain shell. A finished turn that turn check read as work -// still running (a build, a deploy, a watcher) shows as running, and one it -// read as parked until a reply or a later time as ready (Idle). -export type SessionState = "ready" | "running" | "waiting" | "finished" | "exited" | "idle"; - -export const AGENTS = ["claude", "codex", "opencode", "gemini", "pi", "omp", "cursor-agent"]; - -export function agentOf(s: Session): string | undefined { - // A service's terminal runs no agent, whatever its command. - if (s.service) return undefined; - if (s.agent) return s.agent; - const program = s.command?.trim().split(/\s+/)[0]?.split("/").pop(); - return program && AGENTS.includes(program) ? program : undefined; -} - -// atQuestion says an agent shown as waiting waits on a question of its own, -// on its screen or from its hooks. Turn check's wait (soft_wait) is not one: -// its question is its last message, and a prompt typed then is a new turn. -export const atQuestion = (s: Session | undefined, state: string | undefined): boolean => state === "waiting" && !s?.soft_wait; - -export function sessionState(s: Session, stats?: Stats): SessionState { - if (s.exited) return "exited"; - // Never another agent's state in the same worktree. - if (s.service) return "idle"; - if (s.agent_state === "finished" && s.unfinished) return "running"; - if (s.agent_state === "finished" && s.parked) return "ready"; - if (s.agent_state) return s.agent_state === "idle" ? "ready" : s.agent_state; - // The box's report is per folder: a state from before this session began - // is another agent's in the same worktree, not this one's (a new agent - // would show the last one's question or "finished"). - const born = Date.parse(s.created); - const reported = stats?.agents?.find((a) => a.path === s.dir && a.state !== "running" && !(born && a.since && Date.parse(a.since) < born)); - if (reported) return reported.state === "idle" ? "ready" : reported.state; - return agentOf(s) ? "running" : "idle"; -} - -// onItsWork says a session shown as running is not in a turn: its turn -// ended, and turn check read its work as running on without it (a delegated -// task it waits on, a build, a deploy, a watcher). It is drawn with an -// hourglass, not a live turn's spinner, and says why in ON_ITS_WORK. -export const onItsWork = (s: Session | undefined): boolean => !!s && !s.exited && !s.service && s.agent_state === "finished" && !!s.unfinished; - -export const ON_ITS_WORK = "Its turn ended while its work runs on: a delegated task, a build, a deploy or a watcher. It picks up by itself."; - -// allOnItsWork says every session of these shown as running is on its work, -// with no live turn among them: a row that sums them up shows the hourglass. -export function allOnItsWork(sessions: Session[], stats?: Stats): boolean { - const running = sessions.filter((s) => sessionState(s, stats) === "running"); - return running.length > 0 && running.every(onItsWork); -} - -// chatState is the state a chat draws a session in: one on its work is -// between turns, so its chat is a finished turn's (Send; no spinner, timer -// or Stop), with the hourglass at its foot. Everywhere else it is running. -export function chatState(s: Session, stats?: Stats): SessionState { - return onItsWork(s) ? "finished" : sessionState(s, stats); -} - -// replyMode is what a chat's reply box does at a state: queue a message -// for when a live turn ends, answer the agent's question, or send it. -export const replyMode = (state: string | undefined): "send" | "queue" | "answer" => (state === "running" ? "queue" : state === "waiting" ? "answer" : "send"); - -export function worktreeSessions(sessions: Session[] | undefined, wt: Worktree): Session[] { - // A service's terminal is the service, not work in the worktree. - return (sessions ?? []).filter((s) => s.dir === wt.path && !s.service); -} - -// worktreeOf finds the worktree a session runs in. -export function worktreeOf(locations: Location[] | undefined, s: Session): { location: Location; worktree: Worktree } | undefined { - for (const location of locations ?? []) { - for (const worktree of location.worktrees ?? []) { - if (worktree.path === s.dir) return { location, worktree }; - } - } - return undefined; -} - -// offBoard is whether a session runs in a location kept off the Agent -// Dashboard (Settings → Agents). hidden holds "box/location" names; a -// session outside every known worktree stays on the board. -export function offBoard(locations: Location[] | undefined, box: string, s: Session, hidden: ReadonlySet): boolean { - if (!hidden.size) return false; - const where = worktreeOf(locations, s); - return !!where && hidden.has(`${box}/${where.location.name}`); -} - -// sessionName is what the app calls a session everywhere it lists one: its -// title, the work it was started for ("Fix checkout webhook"), or without -// one the agent's name, or "Shell", numbered when its worktree has more -// than one of the same ("Claude Code 2", by when they started). agent adds -// the agent after a title, for text with no agent icon beside it ("Fix -// checkout webhook · Claude Code"); sessionAgent is that part alone, for -// secondary text. Pass sessions (the box's) for the number, and locations -// with place to say where it runs, for lists outside the worktree's own -// tabs: "shop / checkout-fix · Codex". The raw session id belongs in -// tooltips and developer surfaces only. -export function sessionName(s: Session, opts: { sessions?: Session[]; locations?: Location[]; place?: boolean; agent?: boolean } = {}): string { - const title = s.title?.trim(); - const agent = agentOf(s); - let name = title || (agent ? agentLabel(agent) : s.service || "Shell"); - if (title && opts.agent) name += ` · ${agent ? agentLabel(agent) : "Shell"}`; - const same = title ? [] : (opts.sessions ?? []).filter((o) => o.dir === s.dir && agentOf(o) === agent && !o.exited && !o.title?.trim()); - if (same.length > 1) { - const order = same.sort((a, b) => a.created.localeCompare(b.created) || a.name.localeCompare(b.name)); - const n = order.findIndex((o) => o.name === s.name) + 1; - if (n > 1) name += ` ${n}`; - } - if (!opts.place) return name; - return `${sessionPlace(s, opts.locations)} · ${name}`; -} - -// TITLE_MAX is how long a title made from a prompt is, as the box makes it. -export const TITLE_MAX = 48; - -// titleOf is the box's title for a prompt: its first line with words in it, -// spaces collapsed, cut at a word near TITLE_MAX with an ellipsis. The demo -// names its sessions with it; the box does the same for real ones -// (internal/integrations/adapters/title.go). -export function titleOf(prompt: string, max = TITLE_MAX): string { - const line = prompt - .split("\n") - .map((l) => l.trim().replace(/\s+/g, " ")) - .find(Boolean); - if (!line) return ""; - const chars = [...line]; - if (chars.length <= max) return line; - const cut = chars.slice(0, max - 1); - let at = cut.length; - if (chars[max - 1] !== " ") { - for (let i = cut.length - 1; i >= Math.floor((max * 2) / 3); i--) { - if (cut[i] === " ") { - at = i; - break; - } - } - } - return `${cut.slice(0, at).join("").replace(/[\s.,;:-]+$/, "")}…`; -} - -// sessionAgent is the secondary text beside a titled session's name: the -// agent ("Claude Code") or "Shell". Untitled sessions are named after their -// agent already, so it is empty for them. -export function sessionAgent(s: Session): string { - if (s.service) return "Service"; - if (!s.title?.trim()) return ""; - const agent = agentOf(s); - return agent ? agentLabel(agent) : "Shell"; -} - -// guessSessionName names a session the box doesn't list (it has gone, or -// its box is away) from its id, which berthd makes from where and what it -// runs: "evals-judge-claude-3k9" → "evals-judge · Claude Code". An id that -// doesn't follow that shape comes back as it is. -export function guessSessionName(id: string): string { - const at = programIn(id); - if (!at) return id; - const name = at.prog === "shell" ? "Shell" : agentLabel(at.prog); - return at.place ? `${at.place} · ${name}` : name; -} - -// guessAgent is the agent a session id names, for an icon. -export const guessAgent = (id: string): string | undefined => { - const prog = programIn(id)?.prog; - return prog === "shell" ? undefined : prog; -}; - -function programIn(id: string): { prog: string; place: string } | undefined { - const parts = id.split("-"); - for (let i = parts.length - 1; i >= 0; i--) { - const two = parts.slice(i, i + 2).join("-"); - const prog = AGENTS.includes(two) ? two : AGENTS.includes(parts[i]) || parts[i] === "shell" ? parts[i] : undefined; - if (prog) return { prog, place: parts.slice(0, i).join("-") }; - } - return undefined; -} - -// sessionPlace is where a session runs: "shop" for a main checkout, "shop / -// checkout-fix" for a worktree, or "shop / Fix checkout" once it was given -// a display name. -export function sessionPlace(s: Session, locations?: Location[]): string { - const where = worktreeOf(locations, s); - if (!where) return s.location ?? s.name; - return where.worktree.main ? where.location.name : `${where.location.name} / ${where.worktree.title?.trim() || where.worktree.name}`; -} - -// Worktrees are listed main first, then by name. -export function sortedWorktrees(loc: Location): Worktree[] { - return [...(loc.worktrees ?? [])].sort((a, b) => Number(!!b.main) - Number(!!a.main) || a.name.localeCompare(b.name)); -} - -const labels: Record = { claude: "Claude Code", codex: "Codex", opencode: "OpenCode", gemini: "Gemini", pi: "Pi", omp: "oh-my-pi", "cursor-agent": "Cursor Agent", cursor: "Cursor Agent" }; - -// agentLabel is an agent's product name: "claude" → "Claude Code". -export const agentLabel = (a: string) => labels[a] ?? a.charAt(0).toUpperCase() + a.slice(1); - -// restartCommand is how to start an agent again: its command without the -// first prompt it was given (berth adds it last, shell-quoted, after -// --prompt or -i for the agents that take one), so starting again doesn't -// run the old task a second time. -export function restartCommand(command?: string): string | undefined { - if (!command) return command; - return command.replace(/(?:\s+(?:--prompt|-i))?\s+'(?:[^']|'\\'')*'\s*$/, ""); -} - -// firstPrompt is that prompt, unquoted, for a session Shipyard started with -// an agent preset (whose command it wrote); undefined for anything else. -export function firstPrompt(s?: Pick): string | undefined { - if (!s?.preset || !s.command) return undefined; - const m = s.command.match(/\s'((?:[^']|'\\'')*)'\s*$/); - return m ? m[1].replaceAll("'\\''", "'") : undefined; -} +// Shared with the phone app: packages/core. +export * from "../../../packages/core/src/derive.ts"; diff --git a/app/src/lib/format.ts b/app/src/lib/format.ts index 8dd7b3231..3976b3f61 100644 --- a/app/src/lib/format.ts +++ b/app/src/lib/format.ts @@ -1,24 +1,2 @@ -export function bytes(n: number): string { - if (n < 1024) return `${n} B`; - const units = ["KB", "MB", "GB", "TB"]; - let v = n / 1024; - let i = 0; - while (v >= 1024 && i < units.length - 1) { - v /= 1024; - i++; - } - return `${v >= 100 ? v.toFixed(0) : v.toFixed(1)} ${units[i]}`; -} - -export function ago(iso?: string): string { - if (!iso) return ""; - const s = Math.max(0, (Date.now() - new Date(iso).getTime()) / 1000); - if (s < 60) return "just now"; - if (s < 3600) return `${Math.floor(s / 60)}m ago`; - if (s < 86400) return `${Math.floor(s / 3600)}h ago`; - return `${Math.floor(s / 86400)}d ago`; -} - -export function errorMessage(err: unknown): string { - return err instanceof Error ? err.message : String(err); -} +// Shared with the phone app: packages/core. +export * from "../../../packages/core/src/format.ts"; diff --git a/app/src/lib/net.ts b/app/src/lib/net.ts index 3ba541bbf..733bc038d 100644 --- a/app/src/lib/net.ts +++ b/app/src/lib/net.ts @@ -1,96 +1,2 @@ -// How the app behaves on a slow or dropping network: the pure parts, so -// they are easy to check (net.test.ts). The laptop agent holds the -// connection to every box; when a box is away it tries again on a backoff -// and says when (retry_at), and answers requests for it at once with 503 -// rather than letting them wait out a dial. The app adds a time limit to -// reads, so nothing spins forever, follows the agent's event stream with a -// watchdog and jittered backoff, and never runs two full refreshes at once. - -// A read gets this long before it fails as "didn't answer". Long polls -// (…/wait) carry their own timeout and are left alone, and so are writes, -// which can take long (a worktree's setup) and must not be cut off midway. -export const READ_TIMEOUT_MS = 30_000; - -export function readTimeout(method: string, path: string): number | undefined { - if (method !== "GET") return undefined; - const p = path.split("?")[0]; - if (/\/wait$/.test(p) || p.endsWith("/v1/events")) return undefined; - return READ_TIMEOUT_MS; -} - -// reconnectDelay is the wait before the attempt-th reconnect of a stream -// (1 is the first): 500ms doubling to 10s, give or take 20%, so many -// windows (or apps) that lost the agent together don't come back as one. -export function reconnectDelay(attempt: number, random: () => number = Math.random): number { - const base = Math.min(500 * 2 ** Math.max(0, attempt - 1), 10_000); - return Math.round(base * (0.8 + 0.4 * random())); -} - -// The agent writes to the event stream at least every 20s (a keepalive); -// a stream silent for longer than this is dead though not closed (the agent -// paused, a sleep), and is opened again. -export const STREAM_SILENCE_MS = 45_000; - -// coalesce wraps an async job so calls while it runs don't start another: -// they get one more run once it ends, which sees everything they asked -// for. A reconnect, a focus, an event and the poll landing together cost -// one refresh, then at most one more. -export function coalesce(job: () => Promise): () => Promise { - let running: Promise | undefined; - let again: Promise | undefined; - const run = (): Promise => { - if (!running) { - running = job().finally(() => { - running = undefined; - }); - return running; - } - if (!again) { - // After it, however it ended: a failed refresh doesn't stop the next. - again = running - .catch(() => {}) - .then(() => { - again = undefined; - return run(); - }); - } - return again; - }; - return run; -} - -// A box that is away, as the app shows it. -export interface Away { - // Seconds to the agent's next try (0: trying now), when it said. - next?: number; - // Tries in a row that failed. - attempts?: number; - // How long the box has been away, in seconds. - away?: number; -} - -// awayFrom reads a box's status at a moment (ms). -export function awayFrom(st: { state?: string; retry_at?: string; attempts?: number; since?: string } | undefined, now: number): Away { - if (!st || st.state === "online") return {}; - const at = st.retry_at ? Date.parse(st.retry_at) : NaN; - const since = st.since ? Date.parse(st.since) : NaN; - return { - next: Number.isFinite(at) ? Math.max(0, Math.ceil((at - now) / 1000)) : undefined, - attempts: st.attempts, - away: Number.isFinite(since) ? Math.max(0, Math.floor((now - since) / 1000)) : undefined, - }; -} - -// retryLine is the line under "Reconnecting to box…". -export function retryLine(a: Away): string { - const parts: string[] = []; - if (a.next !== undefined) parts.push(a.next > 0 ? `Next try in ${a.next}s` : "Trying now…"); - if (a.away !== undefined && a.away >= 5) parts.push(`away ${duration(a.away)}`); - return parts.join(" · "); -} - -function duration(s: number): string { - if (s < 60) return `${s}s`; - if (s < 3600) return `${Math.floor(s / 60)}m${s % 60 ? ` ${s % 60}s` : ""}`; - return `${Math.floor(s / 3600)}h ${Math.floor((s % 3600) / 60)}m`; -} +// Shared with the phone app: packages/core. +export * from "../../../packages/core/src/net.ts"; diff --git a/app/src/lib/phone.ts b/app/src/lib/phone.ts index 5664cd334..bcd84fb57 100644 --- a/app/src/lib/phone.ts +++ b/app/src/lib/phone.ts @@ -29,20 +29,8 @@ export const phoneApi = { change: (c: Client, box: string, change: PhoneChange) => c.box(box, "PUT", "phone", change), }; -export interface PairedBox { - name: string; - url: string; - token: string; -} - -// pairingLink opens the first box's phone app and hands it every box, in -// the URL fragment so the tokens never reach a server or its logs. -export function pairingLink(boxes: PairedBox[]): string | undefined { - if (!boxes.length) return undefined; - const json = JSON.stringify(boxes.map((b) => ({ name: b.name, url: b.url, token: b.token }))); - const b64 = btoa(unescape(encodeURIComponent(json))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); - return `${new URL(boxes[0].url).origin}/#pair=${b64}`; -} +// Pairing links are shared with the phone app: packages/core. +export { pairingLink, type PairedBox } from "../../../packages/core/src/pairing.ts"; // A topic only you know is what keeps ntfy notifications private. export function newNtfyTopic(): string { diff --git a/app/src/lib/questions.ts b/app/src/lib/questions.ts index 753342ea6..a908f297e 100644 --- a/app/src/lib/questions.ts +++ b/app/src/lib/questions.ts @@ -1,99 +1,9 @@ import type { Client } from "@/lib/api"; -import type { TranscriptItem } from "@/lib/transcript"; +import type { QuestionAnswer } from "../../../packages/core/src/questions.ts"; -// Questions an agent asks with a form of its own: Claude Code's -// AskUserQuestion (one to four questions, each with its options, some -// taking several picks, each with room for the person's own words) and -// Codex's request_user_input. The box reads them from the agent's record -// (a "question" item) and, for Claude Code, fills in its form with keys -// from the whole answer set (POST …/answer, the "answer" capability), -// checking its screen after every key. - -export interface Question { - question: string; - header?: string; - // Takes several picks (checkboxes) rather than one (radios). - multi?: boolean; - options: { label: string; description?: string }[]; - // Codex's name for the question. - id?: string; -} - -// One question's answer: the options picked, by label, and the person's -// own words (Other). -export interface QuestionAnswer { - picks: string[]; - other?: string; -} +export * from "../../../packages/core/src/questions.ts"; +// The box fills in Claude Code's form with keys from the whole answer set +// (the "answer" capability). export const answerQuestions = (c: Client, box: string, session: string, req: { tool: string; answers: QuestionAnswer[] }) => c.box<{ answered: string[] }>(box, "POST", `sessions/${encodeURIComponent(session)}/answer`, req); - -// shownAnswer is an answer as the agent shows it: the options picked, in -// their order, then the person's own words. -export function shownAnswer(q: Question, a: QuestionAnswer | undefined): string { - if (!a) return ""; - const parts = q.options.filter((o) => a.picks.includes(o.label)).map((o) => o.label); - const other = (a.other ?? "").replace(/\s+/g, " ").trim(); - if (other) parts.push(other); - return parts.join(", "); -} - -// complete says a question has its answer: one pick or the person's words -// for a single choice, at least one of either for several. -export function complete(q: Question, a: QuestionAnswer | undefined): boolean { - if (!a) return false; - const n = a.picks.length + ((a.other ?? "").trim() ? 1 : 0); - return q.multi ? n > 0 : n === 1; -} - -// answersText is every answer as plain text, one line each under its -// question's name, for the person to paste into the agent's own screen -// when the box couldn't fill in its form. -export function answersText(questions: Question[], answers: (QuestionAnswer | undefined)[]): string { - return questions.map((q, i) => `${q.header || q.question.split("\n")[0]}: ${shownAnswer(q, answers[i]) || "—"}`).join("\n"); -} - -// lastQuestion is the form of questions the agent asked last, unless the -// person has spoken since. Another agent's word after it (a helper back -// from the background, its hand-back) is no answer. -export function lastQuestion(items: TranscriptItem[]): Extract | undefined { - for (let i = items.length - 1; i >= 0; i--) { - const it = items[i]; - if (it.kind === "question") return it; - if (it.kind === "user") return undefined; - } -} - -// What a waiting agent offers the chat to answer it with. -export interface Waiting { - // Runs structured (lib/structured): it has no screen of its own. - structured: boolean; - // A form of questions from its record, and whether the box fills it in. - form: boolean; - answerable: boolean; - // Its screen shows a form no one number answers. - screenForm: boolean; - // The options read (its screen's, or its ask's), and whether they are - // still being read. - choices: number; - reading: boolean; - // Its hooks or its driver said what it asks. - asked: boolean; - // The question card drawn, not yet answered: its options, and whether - // its hooks described it. - card?: { choices: number; hooks: boolean }; - // An option picked that asks for words, which the reply box types. - wantsWords: boolean; -} - -// atMenu says the reply box waits for a pick above: Enter there would pick -// for the agent. A structured agent has no screen to answer at, so only -// something to pick here holds it; with nothing, the reply is the answer -// (its box says no to the ask and gives the agent the words). -export function atMenu(w: Waiting): boolean { - if (w.wantsWords) return false; - const card = w.card?.choices ?? 0; - if (w.structured) return w.answerable || w.reading || w.choices > 0 || card > 0; - return w.form || w.screenForm || w.choices > 0 || w.asked || card > 0 || !!w.card?.hooks; -} diff --git a/app/src/lib/screen.ts b/app/src/lib/screen.ts index 2847a1604..52b45b0cc 100644 --- a/app/src/lib/screen.ts +++ b/app/src/lib/screen.ts @@ -1,145 +1,2 @@ -// Reading agents' screens: the lines that say what they are doing, and the -// numbered options they ask about. Pure, so anything can use them. - -// Agents draw chrome under their output: an input box, a prompt, hints. -// None of it says what the agent is doing, so the tail skips it. -const RULE = /^[\s─━│┃╭╮╰╯═┌┐└┘├┤┬┴┼▔▁-]+$/; -const CHROME = [ - /^[❯>›$#%]\s*$/, - /^[❯>›]\s+(Try "|$)/, - /^\s*(⏵⏵|⏸|\? for shortcuts|esc to interrupt|bypass permissions|auto mode|accept edits|plan mode)/i, - /·\s*\/effort\s*$/, - /^\s*[●◐◑]\s*(low|medium|high|max)\s*·/i, -]; - -// With blanks, the empty lines between paragraphs stay (one for a run of -// them, none at either end), so a reader can tell paragraphs apart. -export function meaningfulTail(screen: string, count: number, { blanks = false }: { blanks?: boolean } = {}): string[] { - const lines: string[] = []; - for (const raw of screen.split("\n")) { - const l = raw.replace(/\s+$/, ""); - if (!l.trim()) { - if (blanks && lines.length && lines.at(-1) !== "") lines.push(""); - continue; - } - if (!RULE.test(l) && !CHROME.some((re) => re.test(l.trim()))) lines.push(l); - } - while (lines.at(-1) === "") lines.pop(); - const tail = lines.slice(-count); - while (tail[0] === "") tail.shift(); - // Drop the indentation the lines share, so narrow cards show words. - const indent = Math.min(...tail.filter(Boolean).map((l) => l.length - l.trimStart().length)); - return tail.map((l) => l.slice(indent)); -} - -export interface Choice { - key: string; - label: string; - // The option as the agent words it, when label is shorter. - title?: string; -} - -// permissionChoices matches a permission menu's numbered options to the -// three answers a person gives: Allow, Always allow (when the agent offers -// it, e.g. "Yes, and don't ask again for ls commands"), and Deny. The key -// stays the option's own number, so answering types what the agent shows. -export function permissionChoices(choices: Choice[]): Choice[] | undefined { - const always = choices.find((c) => /don.t ask again|always|allow all|this session/i.test(c.label)); - const allow = choices.find((c) => c !== always && /^(yes|allow|approve|proceed)\b/i.test(c.label)); - const deny = choices.find((c) => /^(no|deny|reject)\b/i.test(c.label)); - if (!allow || !deny) return undefined; - return [ - { key: allow.key, label: "Allow", title: allow.label }, - ...(always ? [{ key: always.key, label: "Always allow", title: always.label }] : []), - { key: deny.key, label: "Deny", title: deny.label }, - ]; -} - -// choicesIn reads the numbered options an agent is asking about, such as -// Claude Code's "❯ 1. Yes / 2. No, and tell Claude what to do differently". -export function choicesIn(screen: string): Choice[] { - // A form of questions isn't answered by one number: each picks for the - // question on show and moves on, or ticks a box. - if (questionFormIn(screen)) return []; - return menuIn(screen).choices; -} - -// menuIn reads the numbered options in a screen's last lines, the screen's -// lines, and which of them holds option 1 (-1 with no menu). -function menuIn(screen: string): { choices: Choice[]; lines: string[]; first: number } { - // A pane taller than what the agent drew ends in blank lines. - const lines = screen.trimEnd().split("\n"); - const out: Choice[] = []; - let first = -1; - for (let i = Math.max(0, lines.length - 14); i < lines.length; i++) { - const m = lines[i].match(/^\s*(?:[❯›>]\s*)?(\d)[.)]\s+(\S.*)$/); - if (!m || out.some((c) => c.key === m[1])) continue; - if (!out.length) first = i; - out.push({ key: m[1], label: m[2].trim() }); - } - // A real menu counts up from 1. - return out.length >= 2 && out[0].key === "1" ? { choices: out.slice(0, 4), lines, first } : { choices: [], lines, first: -1 }; -} - -// askIn reads what a waiting agent's screen asks: the numbered options of -// its menu, the line above the first as the question, and whether it is a -// form of questions no one number answers. At its own prompt it asks -// nothing (a list in its last message is no menu), and the question is -// never its chrome (a rule, its footer's "/rc") or the prompt the person -// typed ("❯ /rc"), which end the search. -export function askIn(screen: string): { detail: string; choices: Choice[]; form: boolean } { - const form = questionFormIn(screen); - const none = { detail: "", choices: [], form }; - if (form || screenAt(undefined, screen) === "prompt") return none; - const { choices, lines, first } = menuIn(screen); - if (!choices.length) return none; - for (let i = first - 1; i >= 0; i--) { - const l = lines[i].replace(/^[│|╭╰\s]+|[│|╮╯\s]+$/g, ""); - if (!l) continue; - const chrome = RULE.test(l) || /^[❯>›]\s/.test(l) || CHROME.some((re) => re.test(l)); - return { detail: chrome ? "" : l, choices, form }; - } - return { ...none, choices }; -} - -// questionFormIn says the screen's foot shows Claude Code's form of -// questions with steps: its tab row ("← ☐ Colour ☐ Toppings ✔ Submit -// →"), drawn for several questions or one taking several picks. One -// question with one pick shows a single "☐ Drink" and answers by number. -export function questionFormIn(screen: string): boolean { - return screen - .trimEnd() - .split("\n") - .slice(-40) - .some((l) => /^\s*←\s+[☐☒]/.test(l) || (/[☐☒]/.test(l) && /✔\s*Submit/.test(l))); -} - -// What an agent's screen shows at its foot: its own prompt, waiting for -// words ("prompt"); a screen of its own that only keys can answer, such as -// /model's picker, /config, a trust dialog ("interactive"); or neither for -// sure ("unknown"). Claude Code draws its prompt between two rules; Codex a -// "›" line over its footer. Its own screens end in key hints ("Esc to -// cancel", "Enter to confirm", "↑/↓ to navigate") or numbered options. -// Claude Code 2.1 follows its "❯" with a no-break space, which \s takes. -const PROMPT_RULE = /^\s*[─━]{8,}\s*$/; -const KEY_HINT = /(esc to (cancel|close|go back|exit|clear|dismiss)|enter to (confirm|select|continue|change|set|submit|save|toggle)|press enter|space to (select|toggle)|↑\/↓|←\/→|to navigate|to switch|type to (filter|search))/i; - -export function screenAt(agent: string | undefined, screen: string): "prompt" | "interactive" | "unknown" { - const lines = screen.replace(/\s+$/, "").split("\n").map((l) => l.replace(/\s+$/, "")); - const tail = lines.slice(-16); - const hinted = tail.filter((l) => l.trim()).slice(-4).some((l) => KEY_HINT.test(l)); - let prompt = false; - if (agent === "codex") { - // The input line sits within the last few lines, over the footer. - const last = tail.filter((l) => l.trim()).slice(-4); - prompt = last.some((l) => /^›(\s|$)/.test(l)) && !hinted; - } else { - for (let i = 1; i < tail.length - 1 && !prompt; i++) { - if (!/^\s*[❯>!#](\s|$)/.test(tail[i]) || !PROMPT_RULE.test(tail[i - 1])) continue; - prompt = tail.slice(i + 1, i + 10).some((l) => PROMPT_RULE.test(l)); - } - } - if (prompt) return "prompt"; - if (hinted || choicesIn(screen).length) return "interactive"; - return "unknown"; -} +// Shared with the phone app: packages/core. +export * from "../../../packages/core/src/screen.ts"; diff --git a/app/src/lib/state-model.ts b/app/src/lib/state-model.ts index cf801f8ab..f7bf1036d 100644 --- a/app/src/lib/state-model.ts +++ b/app/src/lib/state-model.ts @@ -1,5 +1,4 @@ import type { BoxStatus } from "@/lib/api"; -import type { SessionState } from "@/lib/derive"; import type { BoxData } from "@/lib/store"; // One state model, said the same way everywhere: sidebar rows, tabs, panes, @@ -14,42 +13,8 @@ import type { BoxData } from "@/lib/store"; // nothing else, green is done or online, red is something broken (an // unreachable box, a failed setup), grey is at rest or gone. -export type AgentStatus = "working" | "needs-you" | "done" | "idle" | "ended"; - -// agentStatus is a session's state in the model's words; a plain shell has -// none. -export function agentStatus(s: SessionState): AgentStatus | undefined { - switch (s) { - case "running": - return "working"; - case "waiting": - return "needs-you"; - case "finished": - return "done"; - case "ready": - return "idle"; - case "exited": - return "ended"; - default: - return undefined; - } -} - -export const AGENT_WORDS: Record = { - working: { word: "Working", lower: "working", hint: "Busy on its task" }, - "needs-you": { word: "Needs you", lower: "needs you", hint: "Waiting for your answer or permission" }, - done: { word: "Done", lower: "done", hint: "Finished its turn; look at what it did" }, - idle: { word: "Idle", lower: "idle", hint: "Open with nothing to do; give it a task" }, - ended: { word: "Ended", lower: "ended", hint: "Its program closed; start it again to carry on" }, -}; - -// sessionWord is the one word for a session's state: "Working", "Needs -// you"…, or "Shell" for a plain shell. -export function sessionWord(s: SessionState, lower = false): string { - const a = agentStatus(s); - if (!a) return lower ? "shell" : "Shell"; - return lower ? AGENT_WORDS[a].lower : AGENT_WORDS[a].word; -} +// The agent's words live in packages/core, shared with the phone app. +export * from "../../../packages/core/src/state.ts"; export type BoxState = "online" | "slow" | "outdated" | "offline" | "unreachable" | "connecting"; diff --git a/app/src/lib/transcript.ts b/app/src/lib/transcript.ts index 0605957b0..9cf42a96b 100644 --- a/app/src/lib/transcript.ts +++ b/app/src/lib/transcript.ts @@ -1,202 +1,2 @@ -import type { Question } from "@/lib/questions"; - -// A session's work as a calm transcript rather than a terminal: what Shore -// mode draws. The agent still runs in its terminal on the box; berthd reads -// the agent's own record of the conversation (Claude's transcript, Codex's -// session file, ACP for the rest) and streams it as these items. Nothing is -// kept by Shipyard. - -export type TranscriptItem = - // pending: sent from here, and the agent hasn't read it yet. midTurn: - // typed while the agent worked, which it read at its next step. - | { kind: "user"; id: string; text: string; pending?: boolean; midTurn?: boolean } - // live: words read from the agent's screen that its record doesn't - // have yet (a draft, lib/draft-text), replaced by the record's own once - // it catches up. clipped: the draft's start is above the agent's screen. - | { kind: "text"; id: string; text: string; live?: boolean; clipped?: boolean } - | { kind: "tools"; id: string; verb: string; items?: ToolCall[]; done?: boolean } - | { kind: "edit"; id: string; file: string; added: number; removed: number; tool?: string } - // A question for the person. choices are the agent's own numbered options - // when it shows some; without them it is yes or no (Allow or Deny for a - // command). decided is what was answered. - // A permission the agent's hooks described (structured) names the tool, - // what it would run or touch (detail) and why, rather than a screen line. - // reply: with no options to pick, a reply answers it (a structured - // agent, which has no screen of its own). - | { kind: "ask"; id: string; tool: string; detail: string; choices?: { key: string; label: string; title?: string }[]; decided?: string; why?: string; structured?: boolean; reading?: boolean; reply?: boolean } - // The agent at work: the step it is running (timed from the call), or - // its own word for what it does (label, from its status line) with what - // else that line says (meta: tokens); since is when it began. - | { kind: "thinking"; id: string; since: number; label?: string; elapsed?: string; meta?: string; step?: { verb: string; target: string } } - // Its turn ended while its work runs on (derive's onItsWork): not at work - // itself, so no spinner and no timer. - | { kind: "on-its-work"; id: string } - // A command typed to the agent rather than a prompt: one of its own - // ("/model", with what followed it) or a shell command ("!"), and the - // output its program printed (Markdown when it wrote it so). - | { kind: "command"; id: string; command: string; args?: string; text?: string; markdown?: boolean; error?: boolean } - | { kind: "crew"; id: string; names: string[] } - // Something the person should know, with one next step: an API error, a - // usage or rate limit (resets: when, in ms), a hook that failed, a turn - // they interrupted, an agent that ended (components/conversation/notice-card). - | { kind: "notice"; id: string; notice: NoticeKind; level?: "error" | "warning" | "info"; text: string; resets?: number } - // A page the agent published on claude.ai (Claude Code's Artifact tool): - // text is its title, url its link once the result says it, file what was - // published. Not done yet: still publishing. error: the publish failed. - // updated: it was published before. - // local: an artifact kept on the box instead (`berthd artifact add`, - // components/art), by id, and version the version the command made. - | { kind: "artifact"; id: string; tool?: string; text: string; url?: string; description?: string; file?: string; done?: boolean; error?: boolean; updated?: boolean; local?: string; version?: number } - // Questions the agent asked with a form of its own (Claude Code's - // AskUserQuestion, Codex's request_user_input; lib/questions). Once done, - // answers holds what was answered, one per question; error: it wasn't. - | { kind: "question"; id: string; tool?: string; questions: Question[]; answers?: string[]; done?: boolean; error?: boolean } - // Work this agent started that Shipyard reported back on (a - // typed into its session): a prompt from Shipyard, not - // the person (components/conversation/report-card). - | { kind: "report"; id: string; report: BerthReport } - // A message to the agent from another agent (a helper's hand-back, a - // teammate, another session, the lead), or a status from Claude Code - // itself (ping: a background task done or failed). Never the person's - // (internal/transcript/peer.go, components/conversation/agent-message). - | { kind: "agent-message"; id: string; msg: AgentMessage } - | { kind: "ping"; id: string; msg: AgentMessage }; - -// Who a message to the agent is from. helper is the crew member's id when -// it is one of this agent's helpers, so its conversation can open. -export interface MessageSender { - id: string; - name: string; - // harness: Claude Code itself. - kind: "helper" | "teammate" | "session" | "lead" | "harness"; - // A teammate's own colour (blue, green, yellow…). - color?: string; - helper?: string; -} - -export interface AgentMessage { - from: MessageSender; - // An agent-message's: report, question, update or instruction. - intent?: "report" | "question" | "update" | "instruction"; - // finished, failed or stopped on a message; done, failed, stopped or - // info on a ping. - status?: string; - // A report's first heading and its gist in a line. - title?: string; - summary?: string; - body?: string; - // Where Claude Code saved a report too long for its record (body is its - // preview then). - saved?: string; - task?: string; - // How many times it was said, once more than once. - repeat?: number; - // When it arrived (ms). - at?: number; - // A question the agent answered since, or the person wrote after. - answered?: boolean; -} - -// One piece of work a reports on -// (internal/transcript/report.go). -export interface BerthReport { - kind: "task" | "turn" | "run"; - session?: string; - run?: string; - template?: string; - title?: string; - worktree?: string; - branch?: string; - // finished, failed, exited, lost or waiting; a run's own status. - status: string; - duration?: string; - files?: number; - added?: number; - removed?: number; - summary?: string; - answer?: string; - needs?: string; -} - -export type NoticeKind = "api_error" | "limit" | "rate_limit" | "auth" | "billing" | "hook" | "interrupted" | "stop_failure" | "exited" | "memory"; - -export interface ToolCall { - verb: string; - // When the agent made the call (ms). - at?: number; - target: string; - // Names the call for its details (the full command and output). - id?: string; - // A file the call read or wrote, for its chip. - file?: boolean; -} - -// One helper working beside the agent: a subagent it started, or another -// agent on the same work (an attempt, a reviewer, a loop). -export interface CrewMember { - id: string; - name: string; - kind: "subagent" | "attempt" | "reviewer" | "loop"; - agent: string; - state: "running" | "waiting" | "finished"; - doing: string; - since: number; - // When it came back, so its time stops. - until?: number; -} - -// One page the agent published, as the conversation lists them: the latest -// publish of each, newest last (internal/transcript/artifacts.go). tool is -// the call that last published it; at, when (ms). -export interface Artifact { - url: string; - title: string; - description?: string; - file?: string; - at: number; - tool: string; - updated?: boolean; -} - -// The summary line a finished group of tool calls folds to: "Read 5 files", -// "Searched 2 times". -export function toolSummary(t: Extract): string { - const n = t.items?.length ?? 0; - if (t.verb === "Read") return `Read ${n} file${n === 1 ? "" : "s"}`; - if (t.verb === "Search") return `Searched ${n} time${n === 1 ? "" : "s"}`; - if (t.verb === "Run") return `Ran ${n} command${n === 1 ? "" : "s"}`; - if (t.verb === "Skill") return n === 1 && t.items?.[0] ? `Used the ${t.items[0].target} skill` : `Used ${n} skills`; - return `${t.verb} ${n}`; -} - -// EditHunk is one piece of a change, as a unified diff has it: its lines -// are led by " ", "-" or "+". -export interface EditHunk { - oldStart: number; - oldLines: number; - newStart: number; - newLines: number; - lines: string[]; -} - -// ToolDetail is one tool call opened up, as the agent's terminal shows it: -// the full command and its output, an edit's exact change, a new file. -// Fetched only when someone expands the call. -export interface ToolDetail { - id: string; - name: string; - command?: string; - file?: string; - pattern?: string; - old?: string; - new?: string; - // The change numbered by the file's own lines (Claude Code's record of - // it), when the box has it; otherwise old and new number from 1. - hunks?: EditHunk[]; - output?: string; - truncated?: boolean; - error?: boolean; - pending?: boolean; - // A background shell whose output is still growing. - live?: boolean; -} +// Shared with the phone app: packages/core. +export * from "../../../packages/core/src/transcript.ts"; diff --git a/app/vite.config.ts b/app/vite.config.ts index f1b812cc9..cd71575c7 100644 --- a/app/vite.config.ts +++ b/app/vite.config.ts @@ -179,7 +179,7 @@ export default defineConfig(({ mode }) => ({ host: host || false, // Mock mode reads Leadline's and Database's files from the listing in site/plugins/ // (src/lib/mock-marketplace.ts), which is outside this folder. - fs: { allow: [searchForWorkspaceRoot(process.cwd()), path.resolve(import.meta.dirname, "../site/plugins")] }, + fs: { allow: [searchForWorkspaceRoot(process.cwd()), path.resolve(import.meta.dirname, "../site/plugins"), path.resolve(import.meta.dirname, "../packages/core")] }, hmr: host ? { protocol: "ws", diff --git a/packages/core/README.md b/packages/core/README.md new file mode 100644 index 000000000..3fb08a479 --- /dev/null +++ b/packages/core/README.md @@ -0,0 +1,16 @@ +# @berth/core + +Plain TypeScript that the desktop app (`app/`) and the phone app share: a +session's state and its words, reading an agent's screen, transcript items and +how a chat's list changes, questions, pairing links, timeouts and backoff. + +The rules, which `pnpm check:core` in `app/` enforces: + +- Only relative imports, with their `.ts` extension, and `import type` from + `../../plugin-sdk/src/types.ts`. No packages: Vite, Metro and + `node --experimental-strip-types --test` all load these files as they are. +- No DOM, no `window`, no React. Code that needs them stays in the app. + +`app/src/lib/.ts` re-exports each file, so the app's imports +(`@/lib/derive`) are unchanged. Tests sit beside the code as `*.test.ts` and run +with the app's `pnpm test`. diff --git a/packages/core/package.json b/packages/core/package.json new file mode 100644 index 000000000..abe746374 --- /dev/null +++ b/packages/core/package.json @@ -0,0 +1,7 @@ +{ + "name": "@berth/core", + "version": "0.1.0", + "private": true, + "description": "Plain TypeScript shared by the Shipyard app and the phone app: what a session's state is, reading an agent's screen and transcript, pairing links.", + "type": "module" +} diff --git a/packages/core/src/conversation.ts b/packages/core/src/conversation.ts new file mode 100644 index 000000000..ae487bab4 --- /dev/null +++ b/packages/core/src/conversation.ts @@ -0,0 +1,46 @@ +import type { TranscriptItem } from "./transcript.ts"; + +// How a chat's items change as the box sends more of an agent's record: +// the app's conversation store (app/src/lib/conversation-store.ts) and the +// phone app both keep their lists with these. + +// Where an item's line starts in the agent's record (boxes send it as off; +// 0 is left out). +export const offOf = (it: TranscriptItem) => (it as { off?: number }).off ?? 0; + +// mergeItems replaces items with the same id and appends the rest, as the +// box resends a tool group that was still open. +export function mergeItems(list: TranscriptItem[], incoming: TranscriptItem[]): TranscriptItem[] { + const out = [...list]; + const at = new Map(out.map((it, i) => [it.id, i])); + for (const it of incoming) { + const i = at.get(it.id); + if (i === undefined) { + at.set(it.id, out.length); + out.push(it); + } else out[i] = it; + } + return out; +} + +// resyncItems takes a window the box read afresh: what the chat holds from +// before start stays, the rest is the window's, so nothing it showed goes. +// fresh: another conversation, nothing stays. +export function resyncItems(list: TranscriptItem[], window: TranscriptItem[], start: number, fresh?: boolean): TranscriptItem[] { + const held = fresh ? [] : list.filter((it) => offOf(it) < start); + const ids = new Set(window.map((it) => it.id)); + return [...held.filter((it) => !ids.has(it.id)), ...window]; +} + +// fillItems puts items read between what was held and a window into place, +// or returns undefined when they add nothing. +export function fillItems(list: TranscriptItem[], items: TranscriptItem[]): TranscriptItem[] | undefined { + const have = new Set(list.map((it) => it.id)); + const add = items.filter((it) => !have.has(it.id)); + if (!add.length) return undefined; + // In the record's order; a sort that keeps the order of equals. + return [...list, ...add] + .map((it, i) => [it, i] as const) + .sort((a, b) => offOf(a[0]) - offOf(b[0]) || a[1] - b[1]) + .map(([it]) => it); +} diff --git a/app/src/lib/derive.test.ts b/packages/core/src/derive.test.ts similarity index 97% rename from app/src/lib/derive.test.ts rename to packages/core/src/derive.test.ts index 8c1ce3fd7..369f23e0a 100644 --- a/app/src/lib/derive.test.ts +++ b/packages/core/src/derive.test.ts @@ -1,8 +1,8 @@ -// node --experimental-strip-types --test src/lib/derive.test.ts (pnpm test) +// node --experimental-strip-types --test packages/core/src/derive.test.ts (pnpm test in app/) import assert from "node:assert/strict"; import { test } from "node:test"; -import type { Session } from "@berth/plugin"; +import type { Session } from "../../plugin-sdk/src/types.ts"; import { allOnItsWork, chatState, firstPrompt, offBoard, onItsWork, replyMode, restartCommand, sessionState } from "./derive.ts"; diff --git a/packages/core/src/derive.ts b/packages/core/src/derive.ts new file mode 100644 index 000000000..4312b1a64 --- /dev/null +++ b/packages/core/src/derive.ts @@ -0,0 +1,215 @@ +import type { Location, Session, Stats, Worktree } from "../../plugin-sdk/src/types.ts"; + +// What the app shows for a session: the agent's last reported state ("ready" +// is an agent open with nothing to do yet), "exited" once the program ended, +// or "idle" for a plain shell. A finished turn that turn check read as work +// still running (a build, a deploy, a watcher) shows as running, and one it +// read as parked until a reply or a later time as ready (Idle). +export type SessionState = "ready" | "running" | "waiting" | "finished" | "exited" | "idle"; + +export const AGENTS = ["claude", "codex", "opencode", "gemini", "pi", "omp", "cursor-agent"]; + +export function agentOf(s: Session): string | undefined { + // A service's terminal runs no agent, whatever its command. + if (s.service) return undefined; + if (s.agent) return s.agent; + const program = s.command?.trim().split(/\s+/)[0]?.split("/").pop(); + return program && AGENTS.includes(program) ? program : undefined; +} + +// atQuestion says an agent shown as waiting waits on a question of its own, +// on its screen or from its hooks. Turn check's wait (soft_wait) is not one: +// its question is its last message, and a prompt typed then is a new turn. +export const atQuestion = (s: Session | undefined, state: string | undefined): boolean => state === "waiting" && !s?.soft_wait; + +export function sessionState(s: Session, stats?: Stats): SessionState { + if (s.exited) return "exited"; + // Never another agent's state in the same worktree. + if (s.service) return "idle"; + if (s.agent_state === "finished" && s.unfinished) return "running"; + if (s.agent_state === "finished" && s.parked) return "ready"; + if (s.agent_state) return s.agent_state === "idle" ? "ready" : s.agent_state; + // The box's report is per folder: a state from before this session began + // is another agent's in the same worktree, not this one's (a new agent + // would show the last one's question or "finished"). + const born = Date.parse(s.created); + const reported = stats?.agents?.find((a) => a.path === s.dir && a.state !== "running" && !(born && a.since && Date.parse(a.since) < born)); + if (reported) return reported.state === "idle" ? "ready" : reported.state; + return agentOf(s) ? "running" : "idle"; +} + +// onItsWork says a session shown as running is not in a turn: its turn +// ended, and turn check read its work as running on without it (a delegated +// task it waits on, a build, a deploy, a watcher). It is drawn with an +// hourglass, not a live turn's spinner, and says why in ON_ITS_WORK. +export const onItsWork = (s: Session | undefined): boolean => !!s && !s.exited && !s.service && s.agent_state === "finished" && !!s.unfinished; + +export const ON_ITS_WORK = "Its turn ended while its work runs on: a delegated task, a build, a deploy or a watcher. It picks up by itself."; + +// allOnItsWork says every session of these shown as running is on its work, +// with no live turn among them: a row that sums them up shows the hourglass. +export function allOnItsWork(sessions: Session[], stats?: Stats): boolean { + const running = sessions.filter((s) => sessionState(s, stats) === "running"); + return running.length > 0 && running.every(onItsWork); +} + +// chatState is the state a chat draws a session in: one on its work is +// between turns, so its chat is a finished turn's (Send; no spinner, timer +// or Stop), with the hourglass at its foot. Everywhere else it is running. +export function chatState(s: Session, stats?: Stats): SessionState { + return onItsWork(s) ? "finished" : sessionState(s, stats); +} + +// replyMode is what a chat's reply box does at a state: queue a message +// for when a live turn ends, answer the agent's question, or send it. +export const replyMode = (state: string | undefined): "send" | "queue" | "answer" => (state === "running" ? "queue" : state === "waiting" ? "answer" : "send"); + +export function worktreeSessions(sessions: Session[] | undefined, wt: Worktree): Session[] { + // A service's terminal is the service, not work in the worktree. + return (sessions ?? []).filter((s) => s.dir === wt.path && !s.service); +} + +// worktreeOf finds the worktree a session runs in. +export function worktreeOf(locations: Location[] | undefined, s: Session): { location: Location; worktree: Worktree } | undefined { + for (const location of locations ?? []) { + for (const worktree of location.worktrees ?? []) { + if (worktree.path === s.dir) return { location, worktree }; + } + } + return undefined; +} + +// offBoard is whether a session runs in a location kept off the Agent +// Dashboard (Settings → Agents). hidden holds "box/location" names; a +// session outside every known worktree stays on the board. +export function offBoard(locations: Location[] | undefined, box: string, s: Session, hidden: ReadonlySet): boolean { + if (!hidden.size) return false; + const where = worktreeOf(locations, s); + return !!where && hidden.has(`${box}/${where.location.name}`); +} + +// sessionName is what the app calls a session everywhere it lists one: its +// title, the work it was started for ("Fix checkout webhook"), or without +// one the agent's name, or "Shell", numbered when its worktree has more +// than one of the same ("Claude Code 2", by when they started). agent adds +// the agent after a title, for text with no agent icon beside it ("Fix +// checkout webhook · Claude Code"); sessionAgent is that part alone, for +// secondary text. Pass sessions (the box's) for the number, and locations +// with place to say where it runs, for lists outside the worktree's own +// tabs: "shop / checkout-fix · Codex". The raw session id belongs in +// tooltips and developer surfaces only. +export function sessionName(s: Session, opts: { sessions?: Session[]; locations?: Location[]; place?: boolean; agent?: boolean } = {}): string { + const title = s.title?.trim(); + const agent = agentOf(s); + let name = title || (agent ? agentLabel(agent) : s.service || "Shell"); + if (title && opts.agent) name += ` · ${agent ? agentLabel(agent) : "Shell"}`; + const same = title ? [] : (opts.sessions ?? []).filter((o) => o.dir === s.dir && agentOf(o) === agent && !o.exited && !o.title?.trim()); + if (same.length > 1) { + const order = same.sort((a, b) => a.created.localeCompare(b.created) || a.name.localeCompare(b.name)); + const n = order.findIndex((o) => o.name === s.name) + 1; + if (n > 1) name += ` ${n}`; + } + if (!opts.place) return name; + return `${sessionPlace(s, opts.locations)} · ${name}`; +} + +// TITLE_MAX is how long a title made from a prompt is, as the box makes it. +export const TITLE_MAX = 48; + +// titleOf is the box's title for a prompt: its first line with words in it, +// spaces collapsed, cut at a word near TITLE_MAX with an ellipsis. The demo +// names its sessions with it; the box does the same for real ones +// (internal/integrations/adapters/title.go). +export function titleOf(prompt: string, max = TITLE_MAX): string { + const line = prompt + .split("\n") + .map((l) => l.trim().replace(/\s+/g, " ")) + .find(Boolean); + if (!line) return ""; + const chars = [...line]; + if (chars.length <= max) return line; + const cut = chars.slice(0, max - 1); + let at = cut.length; + if (chars[max - 1] !== " ") { + for (let i = cut.length - 1; i >= Math.floor((max * 2) / 3); i--) { + if (cut[i] === " ") { + at = i; + break; + } + } + } + return `${cut.slice(0, at).join("").replace(/[\s.,;:-]+$/, "")}…`; +} + +// sessionAgent is the secondary text beside a titled session's name: the +// agent ("Claude Code") or "Shell". Untitled sessions are named after their +// agent already, so it is empty for them. +export function sessionAgent(s: Session): string { + if (s.service) return "Service"; + if (!s.title?.trim()) return ""; + const agent = agentOf(s); + return agent ? agentLabel(agent) : "Shell"; +} + +// guessSessionName names a session the box doesn't list (it has gone, or +// its box is away) from its id, which berthd makes from where and what it +// runs: "evals-judge-claude-3k9" → "evals-judge · Claude Code". An id that +// doesn't follow that shape comes back as it is. +export function guessSessionName(id: string): string { + const at = programIn(id); + if (!at) return id; + const name = at.prog === "shell" ? "Shell" : agentLabel(at.prog); + return at.place ? `${at.place} · ${name}` : name; +} + +// guessAgent is the agent a session id names, for an icon. +export const guessAgent = (id: string): string | undefined => { + const prog = programIn(id)?.prog; + return prog === "shell" ? undefined : prog; +}; + +function programIn(id: string): { prog: string; place: string } | undefined { + const parts = id.split("-"); + for (let i = parts.length - 1; i >= 0; i--) { + const two = parts.slice(i, i + 2).join("-"); + const prog = AGENTS.includes(two) ? two : AGENTS.includes(parts[i]) || parts[i] === "shell" ? parts[i] : undefined; + if (prog) return { prog, place: parts.slice(0, i).join("-") }; + } + return undefined; +} + +// sessionPlace is where a session runs: "shop" for a main checkout, "shop / +// checkout-fix" for a worktree, or "shop / Fix checkout" once it was given +// a display name. +export function sessionPlace(s: Session, locations?: Location[]): string { + const where = worktreeOf(locations, s); + if (!where) return s.location ?? s.name; + return where.worktree.main ? where.location.name : `${where.location.name} / ${where.worktree.title?.trim() || where.worktree.name}`; +} + +// Worktrees are listed main first, then by name. +export function sortedWorktrees(loc: Location): Worktree[] { + return [...(loc.worktrees ?? [])].sort((a, b) => Number(!!b.main) - Number(!!a.main) || a.name.localeCompare(b.name)); +} + +const labels: Record = { claude: "Claude Code", codex: "Codex", opencode: "OpenCode", gemini: "Gemini", pi: "Pi", omp: "oh-my-pi", "cursor-agent": "Cursor Agent", cursor: "Cursor Agent" }; + +// agentLabel is an agent's product name: "claude" → "Claude Code". +export const agentLabel = (a: string) => labels[a] ?? a.charAt(0).toUpperCase() + a.slice(1); + +// restartCommand is how to start an agent again: its command without the +// first prompt it was given (berth adds it last, shell-quoted, after +// --prompt or -i for the agents that take one), so starting again doesn't +// run the old task a second time. +export function restartCommand(command?: string): string | undefined { + if (!command) return command; + return command.replace(/(?:\s+(?:--prompt|-i))?\s+'(?:[^']|'\\'')*'\s*$/, ""); +} + +// firstPrompt is that prompt, unquoted, for a session Shipyard started with +// an agent preset (whose command it wrote); undefined for anything else. +export function firstPrompt(s?: Pick): string | undefined { + if (!s?.preset || !s.command) return undefined; + const m = s.command.match(/\s'((?:[^']|'\\'')*)'\s*$/); + return m ? m[1].replaceAll("'\\''", "'") : undefined; +} diff --git a/packages/core/src/format.ts b/packages/core/src/format.ts new file mode 100644 index 000000000..8dd7b3231 --- /dev/null +++ b/packages/core/src/format.ts @@ -0,0 +1,24 @@ +export function bytes(n: number): string { + if (n < 1024) return `${n} B`; + const units = ["KB", "MB", "GB", "TB"]; + let v = n / 1024; + let i = 0; + while (v >= 1024 && i < units.length - 1) { + v /= 1024; + i++; + } + return `${v >= 100 ? v.toFixed(0) : v.toFixed(1)} ${units[i]}`; +} + +export function ago(iso?: string): string { + if (!iso) return ""; + const s = Math.max(0, (Date.now() - new Date(iso).getTime()) / 1000); + if (s < 60) return "just now"; + if (s < 3600) return `${Math.floor(s / 60)}m ago`; + if (s < 86400) return `${Math.floor(s / 3600)}h ago`; + return `${Math.floor(s / 86400)}d ago`; +} + +export function errorMessage(err: unknown): string { + return err instanceof Error ? err.message : String(err); +} diff --git a/app/src/lib/net.test.ts b/packages/core/src/net.test.ts similarity index 97% rename from app/src/lib/net.test.ts rename to packages/core/src/net.test.ts index 7b4a9c156..6c38470ef 100644 --- a/app/src/lib/net.test.ts +++ b/packages/core/src/net.test.ts @@ -1,4 +1,4 @@ -// node --experimental-strip-types --test src/lib/net.test.ts (pnpm test) +// node --experimental-strip-types --test packages/core/src/net.test.ts (pnpm test in app/) import assert from "node:assert/strict"; import { test } from "node:test"; diff --git a/packages/core/src/net.ts b/packages/core/src/net.ts new file mode 100644 index 000000000..3ba541bbf --- /dev/null +++ b/packages/core/src/net.ts @@ -0,0 +1,96 @@ +// How the app behaves on a slow or dropping network: the pure parts, so +// they are easy to check (net.test.ts). The laptop agent holds the +// connection to every box; when a box is away it tries again on a backoff +// and says when (retry_at), and answers requests for it at once with 503 +// rather than letting them wait out a dial. The app adds a time limit to +// reads, so nothing spins forever, follows the agent's event stream with a +// watchdog and jittered backoff, and never runs two full refreshes at once. + +// A read gets this long before it fails as "didn't answer". Long polls +// (…/wait) carry their own timeout and are left alone, and so are writes, +// which can take long (a worktree's setup) and must not be cut off midway. +export const READ_TIMEOUT_MS = 30_000; + +export function readTimeout(method: string, path: string): number | undefined { + if (method !== "GET") return undefined; + const p = path.split("?")[0]; + if (/\/wait$/.test(p) || p.endsWith("/v1/events")) return undefined; + return READ_TIMEOUT_MS; +} + +// reconnectDelay is the wait before the attempt-th reconnect of a stream +// (1 is the first): 500ms doubling to 10s, give or take 20%, so many +// windows (or apps) that lost the agent together don't come back as one. +export function reconnectDelay(attempt: number, random: () => number = Math.random): number { + const base = Math.min(500 * 2 ** Math.max(0, attempt - 1), 10_000); + return Math.round(base * (0.8 + 0.4 * random())); +} + +// The agent writes to the event stream at least every 20s (a keepalive); +// a stream silent for longer than this is dead though not closed (the agent +// paused, a sleep), and is opened again. +export const STREAM_SILENCE_MS = 45_000; + +// coalesce wraps an async job so calls while it runs don't start another: +// they get one more run once it ends, which sees everything they asked +// for. A reconnect, a focus, an event and the poll landing together cost +// one refresh, then at most one more. +export function coalesce(job: () => Promise): () => Promise { + let running: Promise | undefined; + let again: Promise | undefined; + const run = (): Promise => { + if (!running) { + running = job().finally(() => { + running = undefined; + }); + return running; + } + if (!again) { + // After it, however it ended: a failed refresh doesn't stop the next. + again = running + .catch(() => {}) + .then(() => { + again = undefined; + return run(); + }); + } + return again; + }; + return run; +} + +// A box that is away, as the app shows it. +export interface Away { + // Seconds to the agent's next try (0: trying now), when it said. + next?: number; + // Tries in a row that failed. + attempts?: number; + // How long the box has been away, in seconds. + away?: number; +} + +// awayFrom reads a box's status at a moment (ms). +export function awayFrom(st: { state?: string; retry_at?: string; attempts?: number; since?: string } | undefined, now: number): Away { + if (!st || st.state === "online") return {}; + const at = st.retry_at ? Date.parse(st.retry_at) : NaN; + const since = st.since ? Date.parse(st.since) : NaN; + return { + next: Number.isFinite(at) ? Math.max(0, Math.ceil((at - now) / 1000)) : undefined, + attempts: st.attempts, + away: Number.isFinite(since) ? Math.max(0, Math.floor((now - since) / 1000)) : undefined, + }; +} + +// retryLine is the line under "Reconnecting to box…". +export function retryLine(a: Away): string { + const parts: string[] = []; + if (a.next !== undefined) parts.push(a.next > 0 ? `Next try in ${a.next}s` : "Trying now…"); + if (a.away !== undefined && a.away >= 5) parts.push(`away ${duration(a.away)}`); + return parts.join(" · "); +} + +function duration(s: number): string { + if (s < 60) return `${s}s`; + if (s < 3600) return `${Math.floor(s / 60)}m${s % 60 ? ` ${s % 60}s` : ""}`; + return `${Math.floor(s / 3600)}h ${Math.floor((s % 3600) / 60)}m`; +} diff --git a/packages/core/src/pairing.test.ts b/packages/core/src/pairing.test.ts new file mode 100644 index 000000000..982d0bf4a --- /dev/null +++ b/packages/core/src/pairing.test.ts @@ -0,0 +1,52 @@ +// node --experimental-strip-types --test packages/core/src/pairing.test.ts (pnpm test in app/) +import assert from "node:assert/strict"; +import { test } from "node:test"; + +import { originOf, pairingLink, parsePairing, type PairedBox } from "./pairing.ts"; + +const boxes: PairedBox[] = [ + { name: "acme-dev", url: "http://100.64.0.7:1379/", token: "a".repeat(48) }, + { name: "acme-büro ✓", url: "http://acme-gpu.tail1234.ts.net:1379", token: "b".repeat(48) }, +]; + +test("a pairing link opens the first box and carries every box", () => { + const link = pairingLink(boxes)!; + assert.match(link, /^http:\/\/100\.64\.0\.7:1379\/#pair=[A-Za-z0-9_-]+$/); + assert.deepEqual(parsePairing(link), [ + { name: "acme-dev", url: "http://100.64.0.7:1379", token: "a".repeat(48) }, + { name: "acme-büro ✓", url: "http://acme-gpu.tail1234.ts.net:1379", token: "b".repeat(48) }, + ]); +}); + +test("the link's base64url is the same as the browser's", () => { + const json = JSON.stringify(boxes.map((b) => ({ name: b.name, url: b.url, token: b.token }))); + const want = Buffer.from(json, "utf8").toString("base64url"); + assert.equal(pairingLink(boxes), `http://100.64.0.7:1379/#pair=${want}`); +}); + +test("a link pasted inside a message still pairs", () => { + const link = pairingLink(boxes.slice(0, 1))!; + assert.equal(parsePairing(`Open this on your phone: ${link} (Shipyard)`)?.length, 1); +}); + +test("a single box, not in a list, pairs", () => { + const b64 = Buffer.from(JSON.stringify({ url: "http://100.64.0.9:1379", token: "c".repeat(48) })).toString("base64url"); + assert.deepEqual(parsePairing(`#pair=${b64}`), [{ name: "100.64.0.9", url: "http://100.64.0.9:1379", token: "c".repeat(48) }]); +}); + +test("damaged links and boxes without a token or web address pair nothing", () => { + const enc = (v: unknown) => "#pair=" + Buffer.from(JSON.stringify(v)).toString("base64url"); + assert.equal(parsePairing("http://100.64.0.7:1379/"), undefined); + assert.equal(parsePairing("#pair=not*base64"), undefined); + assert.equal(parsePairing("#pair=" + Buffer.from("{oops").toString("base64url")), undefined); + assert.equal(parsePairing("#pair=" + Buffer.from([0xff, 0xfe]).toString("base64url")), undefined); + assert.equal(parsePairing(enc([{ name: "x", url: "http://100.64.0.7:1379" }])), undefined); + assert.equal(parsePairing(enc([{ name: "x", url: "javascript:alert(1)", token: "t" }])), undefined); + assert.equal(parsePairing(enc([{ name: "x", url: "http://user@evil:1379", token: "t" }])), undefined); +}); + +test("an origin is the scheme, host and port", () => { + assert.equal(originOf("HTTP://Acme.TS.net:1379/#s=x"), "http://acme.ts.net:1379"); + assert.equal(originOf("https://[fd7a::1]:1379/path"), "https://[fd7a::1]:1379"); + assert.equal(originOf("ftp://acme"), undefined); +}); diff --git a/packages/core/src/pairing.ts b/packages/core/src/pairing.ts new file mode 100644 index 000000000..414429aa5 --- /dev/null +++ b/packages/core/src/pairing.ts @@ -0,0 +1,111 @@ +// Pairing a phone with boxes (internal/box/phone.go). The desktop app's QR +// code is a link to the first box's phone page with every box in the URL +// fragment, which never reaches a server or its logs: +// +// http://100.64.0.7:1379/#pair= +// +// The box's own phone page (internal/box/phoneui/app.js) and the phone app +// both read it. No URL, atob or TextEncoder here: React Native lacks some. + +export interface PairedBox { + name: string; + url: string; + token: string; +} + +// pairingLink opens the first box's phone page and hands it every box. +export function pairingLink(boxes: PairedBox[]): string | undefined { + if (!boxes.length) return undefined; + const json = JSON.stringify(boxes.map((b) => ({ name: b.name, url: b.url, token: b.token }))); + return `${originOf(boxes[0].url)}/#pair=${toBase64url(utf8(json))}`; +} + +// parsePairing reads the boxes from a pairing link, or from text holding +// one (a pasted message); undefined when there is none or it is damaged. +export function parsePairing(text: string): PairedBox[] | undefined { + const m = String(text).match(/#pair=([A-Za-z0-9_-]+)/); + if (!m) return undefined; + let list: unknown; + try { + list = JSON.parse(fromUtf8(fromBase64url(m[1]))); + } catch { + return undefined; + } + const out: PairedBox[] = []; + for (const b of Array.isArray(list) ? list : [list]) { + if (!b || typeof b !== "object") continue; + const { name, url, token } = b as Record; + const origin = typeof url === "string" ? originOf(url) : undefined; + if (!origin || typeof token !== "string" || !token) continue; + out.push({ name: typeof name === "string" && name ? name : hostOf(origin), url: origin, token }); + } + return out.length ? out : undefined; +} + +// originOf is a URL's scheme, host and port, lowercased; undefined unless it +// is http or https. +export function originOf(url: string): string | undefined { + const m = url.trim().match(/^(https?):\/\/([^/?#@\s]+)(?=$|[/?#])/i); + return m ? `${m[1].toLowerCase()}://${m[2].toLowerCase()}` : undefined; +} + +const hostOf = (origin: string) => origin.replace(/^https?:\/\//, "").replace(/:\d+$/, "").replace(/^\[|\]$/g, ""); + +const B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + +function toBase64url(bytes: number[]): string { + let out = ""; + for (let i = 0; i < bytes.length; i += 3) { + const n = (bytes[i] << 16) | ((bytes[i + 1] ?? 0) << 8) | (bytes[i + 2] ?? 0); + out += B64[(n >> 18) & 63] + B64[(n >> 12) & 63]; + if (i + 1 < bytes.length) out += B64[(n >> 6) & 63]; + if (i + 2 < bytes.length) out += B64[n & 63]; + } + return out; +} + +function fromBase64url(s: string): number[] { + const out: number[] = []; + let n = 0; + let bits = 0; + for (const c of s) { + const v = B64.indexOf(c); + if (v < 0) throw new Error("not base64url"); + n = (n << 6) | v; + bits += 6; + if (bits >= 8) { + bits -= 8; + out.push((n >> bits) & 255); + } + } + return out; +} + +function utf8(s: string): number[] { + const out: number[] = []; + for (const ch of s) { + const c = ch.codePointAt(0)!; + if (c < 0x80) out.push(c); + else if (c < 0x800) out.push(0xc0 | (c >> 6), 0x80 | (c & 63)); + else if (c < 0x10000) out.push(0xe0 | (c >> 12), 0x80 | ((c >> 6) & 63), 0x80 | (c & 63)); + else out.push(0xf0 | (c >> 18), 0x80 | ((c >> 12) & 63), 0x80 | ((c >> 6) & 63), 0x80 | (c & 63)); + } + return out; +} + +function fromUtf8(bytes: number[]): string { + let out = ""; + for (let i = 0; i < bytes.length; ) { + const b = bytes[i]; + const len = b < 0x80 ? 1 : b >= 0xf0 ? 4 : b >= 0xe0 ? 3 : b >= 0xc0 ? 2 : 0; + if (!len || i + len > bytes.length) throw new Error("not UTF-8"); + let c = len === 1 ? b : b & (0xff >> (len + 1)); + for (let k = 1; k < len; k++) { + if ((bytes[i + k] & 0xc0) !== 0x80) throw new Error("not UTF-8"); + c = (c << 6) | (bytes[i + k] & 63); + } + out += String.fromCodePoint(c); + i += len; + } + return out; +} diff --git a/app/src/lib/questions.test.ts b/packages/core/src/questions.test.ts similarity index 97% rename from app/src/lib/questions.test.ts rename to packages/core/src/questions.test.ts index 9f80a0628..84fd65a3f 100644 --- a/app/src/lib/questions.test.ts +++ b/packages/core/src/questions.test.ts @@ -1,4 +1,4 @@ -// node --experimental-strip-types --test src/lib/questions.test.ts (pnpm test) +// node --experimental-strip-types --test packages/core/src/questions.test.ts (pnpm test in app/) import assert from "node:assert/strict"; import { test } from "node:test"; diff --git a/packages/core/src/questions.ts b/packages/core/src/questions.ts new file mode 100644 index 000000000..2efaa58a7 --- /dev/null +++ b/packages/core/src/questions.ts @@ -0,0 +1,95 @@ +import type { TranscriptItem } from "./transcript.ts"; + +// Questions an agent asks with a form of its own: Claude Code's +// AskUserQuestion (one to four questions, each with its options, some +// taking several picks, each with room for the person's own words) and +// Codex's request_user_input. The box reads them from the agent's record +// (a "question" item) and, for Claude Code, fills in its form with keys +// from the whole answer set (POST …/answer, the "answer" capability), +// checking its screen after every key. + +export interface Question { + question: string; + header?: string; + // Takes several picks (checkboxes) rather than one (radios). + multi?: boolean; + options: { label: string; description?: string }[]; + // Codex's name for the question. + id?: string; +} + +// One question's answer: the options picked, by label, and the person's +// own words (Other). +export interface QuestionAnswer { + picks: string[]; + other?: string; +} + +// shownAnswer is an answer as the agent shows it: the options picked, in +// their order, then the person's own words. +export function shownAnswer(q: Question, a: QuestionAnswer | undefined): string { + if (!a) return ""; + const parts = q.options.filter((o) => a.picks.includes(o.label)).map((o) => o.label); + const other = (a.other ?? "").replace(/\s+/g, " ").trim(); + if (other) parts.push(other); + return parts.join(", "); +} + +// complete says a question has its answer: one pick or the person's words +// for a single choice, at least one of either for several. +export function complete(q: Question, a: QuestionAnswer | undefined): boolean { + if (!a) return false; + const n = a.picks.length + ((a.other ?? "").trim() ? 1 : 0); + return q.multi ? n > 0 : n === 1; +} + +// answersText is every answer as plain text, one line each under its +// question's name, for the person to paste into the agent's own screen +// when the box couldn't fill in its form. +export function answersText(questions: Question[], answers: (QuestionAnswer | undefined)[]): string { + return questions.map((q, i) => `${q.header || q.question.split("\n")[0]}: ${shownAnswer(q, answers[i]) || "—"}`).join("\n"); +} + +// lastQuestion is the form of questions the agent asked last, unless the +// person has spoken since. Another agent's word after it (a helper back +// from the background, its hand-back) is no answer. +export function lastQuestion(items: TranscriptItem[]): Extract | undefined { + for (let i = items.length - 1; i >= 0; i--) { + const it = items[i]; + if (it.kind === "question") return it; + if (it.kind === "user") return undefined; + } +} + +// What a waiting agent offers the chat to answer it with. +export interface Waiting { + // Runs structured (lib/structured): it has no screen of its own. + structured: boolean; + // A form of questions from its record, and whether the box fills it in. + form: boolean; + answerable: boolean; + // Its screen shows a form no one number answers. + screenForm: boolean; + // The options read (its screen's, or its ask's), and whether they are + // still being read. + choices: number; + reading: boolean; + // Its hooks or its driver said what it asks. + asked: boolean; + // The question card drawn, not yet answered: its options, and whether + // its hooks described it. + card?: { choices: number; hooks: boolean }; + // An option picked that asks for words, which the reply box types. + wantsWords: boolean; +} + +// atMenu says the reply box waits for a pick above: Enter there would pick +// for the agent. A structured agent has no screen to answer at, so only +// something to pick here holds it; with nothing, the reply is the answer +// (its box says no to the ask and gives the agent the words). +export function atMenu(w: Waiting): boolean { + if (w.wantsWords) return false; + const card = w.card?.choices ?? 0; + if (w.structured) return w.answerable || w.reading || w.choices > 0 || card > 0; + return w.form || w.screenForm || w.choices > 0 || w.asked || card > 0 || !!w.card?.hooks; +} diff --git a/app/src/lib/screen.test.ts b/packages/core/src/screen.test.ts similarity index 98% rename from app/src/lib/screen.test.ts rename to packages/core/src/screen.test.ts index b7e7b11c5..44e86cde3 100644 --- a/app/src/lib/screen.test.ts +++ b/packages/core/src/screen.test.ts @@ -1,4 +1,4 @@ -// node --experimental-strip-types --test src/lib/screen.test.ts (pnpm test) +// node --experimental-strip-types --test packages/core/src/screen.test.ts (pnpm test in app/) import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { join } from "node:path"; diff --git a/packages/core/src/screen.ts b/packages/core/src/screen.ts new file mode 100644 index 000000000..2847a1604 --- /dev/null +++ b/packages/core/src/screen.ts @@ -0,0 +1,145 @@ +// Reading agents' screens: the lines that say what they are doing, and the +// numbered options they ask about. Pure, so anything can use them. + +// Agents draw chrome under their output: an input box, a prompt, hints. +// None of it says what the agent is doing, so the tail skips it. +const RULE = /^[\s─━│┃╭╮╰╯═┌┐└┘├┤┬┴┼▔▁-]+$/; +const CHROME = [ + /^[❯>›$#%]\s*$/, + /^[❯>›]\s+(Try "|$)/, + /^\s*(⏵⏵|⏸|\? for shortcuts|esc to interrupt|bypass permissions|auto mode|accept edits|plan mode)/i, + /·\s*\/effort\s*$/, + /^\s*[●◐◑]\s*(low|medium|high|max)\s*·/i, +]; + +// With blanks, the empty lines between paragraphs stay (one for a run of +// them, none at either end), so a reader can tell paragraphs apart. +export function meaningfulTail(screen: string, count: number, { blanks = false }: { blanks?: boolean } = {}): string[] { + const lines: string[] = []; + for (const raw of screen.split("\n")) { + const l = raw.replace(/\s+$/, ""); + if (!l.trim()) { + if (blanks && lines.length && lines.at(-1) !== "") lines.push(""); + continue; + } + if (!RULE.test(l) && !CHROME.some((re) => re.test(l.trim()))) lines.push(l); + } + while (lines.at(-1) === "") lines.pop(); + const tail = lines.slice(-count); + while (tail[0] === "") tail.shift(); + // Drop the indentation the lines share, so narrow cards show words. + const indent = Math.min(...tail.filter(Boolean).map((l) => l.length - l.trimStart().length)); + return tail.map((l) => l.slice(indent)); +} + +export interface Choice { + key: string; + label: string; + // The option as the agent words it, when label is shorter. + title?: string; +} + +// permissionChoices matches a permission menu's numbered options to the +// three answers a person gives: Allow, Always allow (when the agent offers +// it, e.g. "Yes, and don't ask again for ls commands"), and Deny. The key +// stays the option's own number, so answering types what the agent shows. +export function permissionChoices(choices: Choice[]): Choice[] | undefined { + const always = choices.find((c) => /don.t ask again|always|allow all|this session/i.test(c.label)); + const allow = choices.find((c) => c !== always && /^(yes|allow|approve|proceed)\b/i.test(c.label)); + const deny = choices.find((c) => /^(no|deny|reject)\b/i.test(c.label)); + if (!allow || !deny) return undefined; + return [ + { key: allow.key, label: "Allow", title: allow.label }, + ...(always ? [{ key: always.key, label: "Always allow", title: always.label }] : []), + { key: deny.key, label: "Deny", title: deny.label }, + ]; +} + +// choicesIn reads the numbered options an agent is asking about, such as +// Claude Code's "❯ 1. Yes / 2. No, and tell Claude what to do differently". +export function choicesIn(screen: string): Choice[] { + // A form of questions isn't answered by one number: each picks for the + // question on show and moves on, or ticks a box. + if (questionFormIn(screen)) return []; + return menuIn(screen).choices; +} + +// menuIn reads the numbered options in a screen's last lines, the screen's +// lines, and which of them holds option 1 (-1 with no menu). +function menuIn(screen: string): { choices: Choice[]; lines: string[]; first: number } { + // A pane taller than what the agent drew ends in blank lines. + const lines = screen.trimEnd().split("\n"); + const out: Choice[] = []; + let first = -1; + for (let i = Math.max(0, lines.length - 14); i < lines.length; i++) { + const m = lines[i].match(/^\s*(?:[❯›>]\s*)?(\d)[.)]\s+(\S.*)$/); + if (!m || out.some((c) => c.key === m[1])) continue; + if (!out.length) first = i; + out.push({ key: m[1], label: m[2].trim() }); + } + // A real menu counts up from 1. + return out.length >= 2 && out[0].key === "1" ? { choices: out.slice(0, 4), lines, first } : { choices: [], lines, first: -1 }; +} + +// askIn reads what a waiting agent's screen asks: the numbered options of +// its menu, the line above the first as the question, and whether it is a +// form of questions no one number answers. At its own prompt it asks +// nothing (a list in its last message is no menu), and the question is +// never its chrome (a rule, its footer's "/rc") or the prompt the person +// typed ("❯ /rc"), which end the search. +export function askIn(screen: string): { detail: string; choices: Choice[]; form: boolean } { + const form = questionFormIn(screen); + const none = { detail: "", choices: [], form }; + if (form || screenAt(undefined, screen) === "prompt") return none; + const { choices, lines, first } = menuIn(screen); + if (!choices.length) return none; + for (let i = first - 1; i >= 0; i--) { + const l = lines[i].replace(/^[│|╭╰\s]+|[│|╮╯\s]+$/g, ""); + if (!l) continue; + const chrome = RULE.test(l) || /^[❯>›]\s/.test(l) || CHROME.some((re) => re.test(l)); + return { detail: chrome ? "" : l, choices, form }; + } + return { ...none, choices }; +} + +// questionFormIn says the screen's foot shows Claude Code's form of +// questions with steps: its tab row ("← ☐ Colour ☐ Toppings ✔ Submit +// →"), drawn for several questions or one taking several picks. One +// question with one pick shows a single "☐ Drink" and answers by number. +export function questionFormIn(screen: string): boolean { + return screen + .trimEnd() + .split("\n") + .slice(-40) + .some((l) => /^\s*←\s+[☐☒]/.test(l) || (/[☐☒]/.test(l) && /✔\s*Submit/.test(l))); +} + +// What an agent's screen shows at its foot: its own prompt, waiting for +// words ("prompt"); a screen of its own that only keys can answer, such as +// /model's picker, /config, a trust dialog ("interactive"); or neither for +// sure ("unknown"). Claude Code draws its prompt between two rules; Codex a +// "›" line over its footer. Its own screens end in key hints ("Esc to +// cancel", "Enter to confirm", "↑/↓ to navigate") or numbered options. +// Claude Code 2.1 follows its "❯" with a no-break space, which \s takes. +const PROMPT_RULE = /^\s*[─━]{8,}\s*$/; +const KEY_HINT = /(esc to (cancel|close|go back|exit|clear|dismiss)|enter to (confirm|select|continue|change|set|submit|save|toggle)|press enter|space to (select|toggle)|↑\/↓|←\/→|to navigate|to switch|type to (filter|search))/i; + +export function screenAt(agent: string | undefined, screen: string): "prompt" | "interactive" | "unknown" { + const lines = screen.replace(/\s+$/, "").split("\n").map((l) => l.replace(/\s+$/, "")); + const tail = lines.slice(-16); + const hinted = tail.filter((l) => l.trim()).slice(-4).some((l) => KEY_HINT.test(l)); + let prompt = false; + if (agent === "codex") { + // The input line sits within the last few lines, over the footer. + const last = tail.filter((l) => l.trim()).slice(-4); + prompt = last.some((l) => /^›(\s|$)/.test(l)) && !hinted; + } else { + for (let i = 1; i < tail.length - 1 && !prompt; i++) { + if (!/^\s*[❯>!#](\s|$)/.test(tail[i]) || !PROMPT_RULE.test(tail[i - 1])) continue; + prompt = tail.slice(i + 1, i + 10).some((l) => PROMPT_RULE.test(l)); + } + } + if (prompt) return "prompt"; + if (hinted || choicesIn(screen).length) return "interactive"; + return "unknown"; +} diff --git a/packages/core/src/state.ts b/packages/core/src/state.ts new file mode 100644 index 000000000..ec61dfa29 --- /dev/null +++ b/packages/core/src/state.ts @@ -0,0 +1,41 @@ +import type { SessionState } from "./derive.ts"; + +// The agent part of the app's state model (app/src/lib/state-model.ts), +// shared with the phone app: the same words everywhere. + +export type AgentStatus = "working" | "needs-you" | "done" | "idle" | "ended"; + +// agentStatus is a session's state in the model's words; a plain shell has +// none. +export function agentStatus(s: SessionState): AgentStatus | undefined { + switch (s) { + case "running": + return "working"; + case "waiting": + return "needs-you"; + case "finished": + return "done"; + case "ready": + return "idle"; + case "exited": + return "ended"; + default: + return undefined; + } +} + +export const AGENT_WORDS: Record = { + working: { word: "Working", lower: "working", hint: "Busy on its task" }, + "needs-you": { word: "Needs you", lower: "needs you", hint: "Waiting for your answer or permission" }, + done: { word: "Done", lower: "done", hint: "Finished its turn; look at what it did" }, + idle: { word: "Idle", lower: "idle", hint: "Open with nothing to do; give it a task" }, + ended: { word: "Ended", lower: "ended", hint: "Its program closed; start it again to carry on" }, +}; + +// sessionWord is the one word for a session's state: "Working", "Needs +// you"…, or "Shell" for a plain shell. +export function sessionWord(s: SessionState, lower = false): string { + const a = agentStatus(s); + if (!a) return lower ? "shell" : "Shell"; + return lower ? AGENT_WORDS[a].lower : AGENT_WORDS[a].word; +} diff --git a/packages/core/src/transcript.ts b/packages/core/src/transcript.ts new file mode 100644 index 000000000..9d138a7c0 --- /dev/null +++ b/packages/core/src/transcript.ts @@ -0,0 +1,202 @@ +import type { Question } from "./questions.ts"; + +// A session's work as a calm transcript rather than a terminal: what Shore +// mode draws. The agent still runs in its terminal on the box; berthd reads +// the agent's own record of the conversation (Claude's transcript, Codex's +// session file, ACP for the rest) and streams it as these items. Nothing is +// kept by Shipyard. + +export type TranscriptItem = + // pending: sent from here, and the agent hasn't read it yet. midTurn: + // typed while the agent worked, which it read at its next step. + | { kind: "user"; id: string; text: string; pending?: boolean; midTurn?: boolean } + // live: words read from the agent's screen that its record doesn't + // have yet (a draft, lib/draft-text), replaced by the record's own once + // it catches up. clipped: the draft's start is above the agent's screen. + | { kind: "text"; id: string; text: string; live?: boolean; clipped?: boolean } + | { kind: "tools"; id: string; verb: string; items?: ToolCall[]; done?: boolean } + | { kind: "edit"; id: string; file: string; added: number; removed: number; tool?: string } + // A question for the person. choices are the agent's own numbered options + // when it shows some; without them it is yes or no (Allow or Deny for a + // command). decided is what was answered. + // A permission the agent's hooks described (structured) names the tool, + // what it would run or touch (detail) and why, rather than a screen line. + // reply: with no options to pick, a reply answers it (a structured + // agent, which has no screen of its own). + | { kind: "ask"; id: string; tool: string; detail: string; choices?: { key: string; label: string; title?: string }[]; decided?: string; why?: string; structured?: boolean; reading?: boolean; reply?: boolean } + // The agent at work: the step it is running (timed from the call), or + // its own word for what it does (label, from its status line) with what + // else that line says (meta: tokens); since is when it began. + | { kind: "thinking"; id: string; since: number; label?: string; elapsed?: string; meta?: string; step?: { verb: string; target: string } } + // Its turn ended while its work runs on (derive's onItsWork): not at work + // itself, so no spinner and no timer. + | { kind: "on-its-work"; id: string } + // A command typed to the agent rather than a prompt: one of its own + // ("/model", with what followed it) or a shell command ("!"), and the + // output its program printed (Markdown when it wrote it so). + | { kind: "command"; id: string; command: string; args?: string; text?: string; markdown?: boolean; error?: boolean } + | { kind: "crew"; id: string; names: string[] } + // Something the person should know, with one next step: an API error, a + // usage or rate limit (resets: when, in ms), a hook that failed, a turn + // they interrupted, an agent that ended (components/conversation/notice-card). + | { kind: "notice"; id: string; notice: NoticeKind; level?: "error" | "warning" | "info"; text: string; resets?: number } + // A page the agent published on claude.ai (Claude Code's Artifact tool): + // text is its title, url its link once the result says it, file what was + // published. Not done yet: still publishing. error: the publish failed. + // updated: it was published before. + // local: an artifact kept on the box instead (`berthd artifact add`, + // components/art), by id, and version the version the command made. + | { kind: "artifact"; id: string; tool?: string; text: string; url?: string; description?: string; file?: string; done?: boolean; error?: boolean; updated?: boolean; local?: string; version?: number } + // Questions the agent asked with a form of its own (Claude Code's + // AskUserQuestion, Codex's request_user_input; lib/questions). Once done, + // answers holds what was answered, one per question; error: it wasn't. + | { kind: "question"; id: string; tool?: string; questions: Question[]; answers?: string[]; done?: boolean; error?: boolean } + // Work this agent started that Shipyard reported back on (a + // typed into its session): a prompt from Shipyard, not + // the person (components/conversation/report-card). + | { kind: "report"; id: string; report: BerthReport } + // A message to the agent from another agent (a helper's hand-back, a + // teammate, another session, the lead), or a status from Claude Code + // itself (ping: a background task done or failed). Never the person's + // (internal/transcript/peer.go, components/conversation/agent-message). + | { kind: "agent-message"; id: string; msg: AgentMessage } + | { kind: "ping"; id: string; msg: AgentMessage }; + +// Who a message to the agent is from. helper is the crew member's id when +// it is one of this agent's helpers, so its conversation can open. +export interface MessageSender { + id: string; + name: string; + // harness: Claude Code itself. + kind: "helper" | "teammate" | "session" | "lead" | "harness"; + // A teammate's own colour (blue, green, yellow…). + color?: string; + helper?: string; +} + +export interface AgentMessage { + from: MessageSender; + // An agent-message's: report, question, update or instruction. + intent?: "report" | "question" | "update" | "instruction"; + // finished, failed or stopped on a message; done, failed, stopped or + // info on a ping. + status?: string; + // A report's first heading and its gist in a line. + title?: string; + summary?: string; + body?: string; + // Where Claude Code saved a report too long for its record (body is its + // preview then). + saved?: string; + task?: string; + // How many times it was said, once more than once. + repeat?: number; + // When it arrived (ms). + at?: number; + // A question the agent answered since, or the person wrote after. + answered?: boolean; +} + +// One piece of work a reports on +// (internal/transcript/report.go). +export interface BerthReport { + kind: "task" | "turn" | "run"; + session?: string; + run?: string; + template?: string; + title?: string; + worktree?: string; + branch?: string; + // finished, failed, exited, lost or waiting; a run's own status. + status: string; + duration?: string; + files?: number; + added?: number; + removed?: number; + summary?: string; + answer?: string; + needs?: string; +} + +export type NoticeKind = "api_error" | "limit" | "rate_limit" | "auth" | "billing" | "hook" | "interrupted" | "stop_failure" | "exited" | "memory"; + +export interface ToolCall { + verb: string; + // When the agent made the call (ms). + at?: number; + target: string; + // Names the call for its details (the full command and output). + id?: string; + // A file the call read or wrote, for its chip. + file?: boolean; +} + +// One helper working beside the agent: a subagent it started, or another +// agent on the same work (an attempt, a reviewer, a loop). +export interface CrewMember { + id: string; + name: string; + kind: "subagent" | "attempt" | "reviewer" | "loop"; + agent: string; + state: "running" | "waiting" | "finished"; + doing: string; + since: number; + // When it came back, so its time stops. + until?: number; +} + +// One page the agent published, as the conversation lists them: the latest +// publish of each, newest last (internal/transcript/artifacts.go). tool is +// the call that last published it; at, when (ms). +export interface Artifact { + url: string; + title: string; + description?: string; + file?: string; + at: number; + tool: string; + updated?: boolean; +} + +// The summary line a finished group of tool calls folds to: "Read 5 files", +// "Searched 2 times". +export function toolSummary(t: Extract): string { + const n = t.items?.length ?? 0; + if (t.verb === "Read") return `Read ${n} file${n === 1 ? "" : "s"}`; + if (t.verb === "Search") return `Searched ${n} time${n === 1 ? "" : "s"}`; + if (t.verb === "Run") return `Ran ${n} command${n === 1 ? "" : "s"}`; + if (t.verb === "Skill") return n === 1 && t.items?.[0] ? `Used the ${t.items[0].target} skill` : `Used ${n} skills`; + return `${t.verb} ${n}`; +} + +// EditHunk is one piece of a change, as a unified diff has it: its lines +// are led by " ", "-" or "+". +export interface EditHunk { + oldStart: number; + oldLines: number; + newStart: number; + newLines: number; + lines: string[]; +} + +// ToolDetail is one tool call opened up, as the agent's terminal shows it: +// the full command and its output, an edit's exact change, a new file. +// Fetched only when someone expands the call. +export interface ToolDetail { + id: string; + name: string; + command?: string; + file?: string; + pattern?: string; + old?: string; + new?: string; + // The change numbered by the file's own lines (Claude Code's record of + // it), when the box has it; otherwise old and new number from 1. + hunks?: EditHunk[]; + output?: string; + truncated?: boolean; + error?: boolean; + pending?: boolean; + // A background shell whose output is still growing. + live?: boolean; +} diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json new file mode 100644 index 000000000..70c65233c --- /dev/null +++ b/packages/core/tsconfig.json @@ -0,0 +1,21 @@ +{ + // No DOM and no packages: the desktop app (Vite), the phone app (Metro) + // and node's test runner all load these files as they are. Checked by + // app's check:core. + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "ESNext", + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "noEmit": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "types": [] + }, + "include": ["src"], + "exclude": ["src/**/*.test.ts"] +} From c1ec5e07af2f959a5c2305249e5c43b1d1abd9be Mon Sep 17 00:00:00 2001 From: Bailey Pumfleet Date: Thu, 29 Oct 2026 16:10:57 -0500 Subject: [PATCH 2/4] feat(mobile): add Shipyard for iPhone An Expo app (iOS first, Android later from the same code) that pairs with boxes from the desktop app's existing QR code and shows which agents need you across them: a session's conversation or its screen, the answers it offers, keys and a prompt to send; runs, their gates and cancelling them. Boxes at the phone API's version 2 stream their events and send notifications through the push relay; older boxes are read every few seconds. Tokens stay in the keychain, and the demo works without a box. Session state, screen and transcript reading come from packages/core, shared with the desktop app. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 40 + AGENTS.md | 1 + mobile/.gitignore | 44 + mobile/AGENTS.md | 18 + mobile/README.md | 51 + mobile/app.config.ts | 51 + mobile/assets/icon.png | Bin 0 -> 38258 bytes mobile/assets/splash-icon.png | Bin 0 -> 20880 bytes mobile/eas.json | 19 + mobile/metro.config.js | 13 + mobile/package.json | 56 + mobile/pnpm-lock.yaml | 8661 ++++++++++++++++++++++++++ mobile/pnpm-workspace.yaml | 6 + mobile/src/app/(tabs)/_layout.tsx | 47 + mobile/src/app/(tabs)/boxes.tsx | 129 + mobile/src/app/(tabs)/index.tsx | 92 + mobile/src/app/(tabs)/runs.tsx | 51 + mobile/src/app/_layout.tsx | 116 + mobile/src/app/pair.tsx | 125 + mobile/src/app/r/[box]/[run].tsx | 127 + mobile/src/app/s/[box]/[session].tsx | 203 + mobile/src/components/cards.tsx | 71 + mobile/src/components/transcript.tsx | 131 + mobile/src/components/ui.tsx | 134 + mobile/src/lib/api.ts | 61 + mobile/src/lib/choices.test.ts | 52 + mobile/src/lib/choices.ts | 25 + mobile/src/lib/events.test.ts | 70 + mobile/src/lib/events.ts | 113 + mobile/src/lib/links.ts | 34 + mobile/src/lib/mock.ts | 90 + mobile/src/lib/push.ts | 104 + mobile/src/lib/storage.ts | 48 + mobile/src/lib/store.test.ts | 69 + mobile/src/lib/store.ts | 248 + mobile/src/lib/theme.ts | 65 + mobile/src/lib/types.ts | 85 + mobile/tsconfig.json | 16 + 38 files changed, 11266 insertions(+) create mode 100644 mobile/.gitignore create mode 100644 mobile/AGENTS.md create mode 100644 mobile/README.md create mode 100644 mobile/app.config.ts create mode 100644 mobile/assets/icon.png create mode 100644 mobile/assets/splash-icon.png create mode 100644 mobile/eas.json create mode 100644 mobile/metro.config.js create mode 100644 mobile/package.json create mode 100644 mobile/pnpm-lock.yaml create mode 100644 mobile/pnpm-workspace.yaml create mode 100644 mobile/src/app/(tabs)/_layout.tsx create mode 100644 mobile/src/app/(tabs)/boxes.tsx create mode 100644 mobile/src/app/(tabs)/index.tsx create mode 100644 mobile/src/app/(tabs)/runs.tsx create mode 100644 mobile/src/app/_layout.tsx create mode 100644 mobile/src/app/pair.tsx create mode 100644 mobile/src/app/r/[box]/[run].tsx create mode 100644 mobile/src/app/s/[box]/[session].tsx create mode 100644 mobile/src/components/cards.tsx create mode 100644 mobile/src/components/transcript.tsx create mode 100644 mobile/src/components/ui.tsx create mode 100644 mobile/src/lib/api.ts create mode 100644 mobile/src/lib/choices.test.ts create mode 100644 mobile/src/lib/choices.ts create mode 100644 mobile/src/lib/events.test.ts create mode 100644 mobile/src/lib/events.ts create mode 100644 mobile/src/lib/links.ts create mode 100644 mobile/src/lib/mock.ts create mode 100644 mobile/src/lib/push.ts create mode 100644 mobile/src/lib/storage.ts create mode 100644 mobile/src/lib/store.test.ts create mode 100644 mobile/src/lib/store.ts create mode 100644 mobile/src/lib/theme.ts create mode 100644 mobile/src/lib/types.ts create mode 100644 mobile/tsconfig.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33feaaeee..7fe96289b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -294,3 +294,43 @@ jobs: - run: pnpm install --frozen-lockfile # The pages are the repository's docs/ folder; a broken page fails here. - run: pnpm build + + mobile: + # Only what was asked for: see "on" above. + if: github.event_name != 'pull_request' || (github.event.action != 'labeled' || github.event.label.name == 'run-ci') && contains(github.event.pull_request.labels.*.name, 'run-ci') + runs-on: ${{ (vars.SELF_HOSTED == 'true' && github.event_name == 'push' && github.actor == github.repository_owner) && fromJSON('["self-hosted","omarchy"]') || 'ubuntu-latest' }} + defaults: + run: + working-directory: mobile + steps: + # omarchy runs only the owner's pushes; its job-started hook + # (ci/runner/job-started.sh) refuses anything else too. + - name: Only the owner's pushes run on a self-hosted runner + if: runner.environment == 'self-hosted' + working-directory: ${{ runner.temp }} + env: + ACTOR: ${{ github.actor }} + TRIGGERING_ACTOR: ${{ github.triggering_actor }} + OWNER: ${{ github.repository_owner }} + EVENT: ${{ github.event_name }} + run: | + if [ "$ACTOR" != "$OWNER" ] || [ "$TRIGGERING_ACTOR" != "$OWNER" ] || [ "$EVENT" != push ]; then + echo "::error::$EVENT by $ACTOR may not run on a self-hosted runner" + exit 1 + fi + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0 + with: + version: 11 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: 22 + # A self-hosted runner keeps its pnpm store between jobs. + cache: ${{ runner.environment == 'github-hosted' && 'pnpm' || '' }} + cache-dependency-path: mobile/pnpm-lock.yaml + - run: pnpm install --frozen-lockfile + # The phone app (mobile/AGENTS.md). No iOS build here: EAS builds + # it. Metro's bundle checks that packages/core resolves. + - run: pnpm typecheck + - run: pnpm test + - run: pnpm export diff --git a/AGENTS.md b/AGENTS.md index 4cc09f3f2..92015c39b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,6 +6,7 @@ Shipyard (formerly Berth) runs coding agents on your own machines. This repo has - `cmd/berth`, `internal/agent`: the laptop CLI and agent (UI API on 1378, proxy on 1377, phone on 1379). - `app/`: the Tauri 2 + React desktop app (coss-ui, 23 themes). `app/e2e` holds the Playwright suite on mock fixtures. - `packages/core`: plain TypeScript shared by `app/` and the phone app (session state, screen and transcript reading, pairing links). Only relative `./x.ts` imports and the plugin SDK's types; no DOM (`check:core`). `app/src/lib/.ts` re-exports it. +- `mobile/`: the phone app (Expo, iOS first), which talks to boxes' phone API over the tailnet. Its rules are in `mobile/AGENTS.md`; check it with `cd mobile && pnpm typecheck && pnpm test && pnpm export`. - `docs/`: the docs as MDX, built by `docs-site/` (Fumadocs). `site/` is the landing page and `install.sh`. **Names:** "Shipyard" is the brand in everything people read. `berth`, `berthd`, `~/.berth`, `BERTH_*`, `berth://`, `dev.berth.app`, `berth.prefs` and the `berth-*` skill ids are identifiers. Don't rename them; a later change will, with migrations. diff --git a/mobile/.gitignore b/mobile/.gitignore new file mode 100644 index 000000000..5121c9e32 --- /dev/null +++ b/mobile/.gitignore @@ -0,0 +1,44 @@ +# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files + +# dependencies +node_modules/ + +# Expo +.expo/ +dist/ +web-build/ +expo-env.d.ts + +# Native +.kotlin/ +*.orig.* +*.jks +*.p8 +*.p12 +*.key +*.mobileprovision + +# Metro +.metro-health-check* + +# debug +npm-debug.* +yarn-debug.* +yarn-error.* + +# macOS +.DS_Store +*.pem + +# local env files +.env*.local + +# typescript +*.tsbuildinfo + +# generated native folders +/ios +/android + +# expo export (pnpm export) +.expo-export/ diff --git a/mobile/AGENTS.md b/mobile/AGENTS.md new file mode 100644 index 000000000..a8e4a222b --- /dev/null +++ b/mobile/AGENTS.md @@ -0,0 +1,18 @@ +# Working on the phone app + +Shipyard for iPhone (Android later, from this code): Expo SDK 58, React Native, expo-router. The repository's own `AGENTS.md` applies too. + +- **Expo changes every SDK.** Before writing code against an Expo or React Native API, read the docs for the SDK in `package.json` (`https://docs.expo.dev/versions/v58.0.0/`, and `https://docs.expo.dev/llms.txt`), not memory. +- **Add native modules with `npx expo install `**, which picks SDK-matched versions. A module with native code needs a new development build (`eas build --profile development`); Expo Go can't load it, nor receive remote notifications. +- **No `ios/` or `android/`.** They are generated (Continuous Native Generation). Configure native behaviour in `app.config.ts` and config plugins. +- **Routes live in `src/app/`**; everything else in `src/lib` (no React) and `src/components`. +- **Shared code is `packages/core`**, imported as `@berth/core/.ts` (tsconfig paths, Metro's `watchFolders`, Jest's `moduleNameMapper`). Code both apps need goes there, by its rules (`packages/core/README.md`). +- **Boxes are the backend**: each box's phone API on its tailnet address, port 1379 (`docs/reference/phone-api.mdx`, `internal/box/phone.go`, `phonev2.go`). Notifications go through the push relay (`push/`). +- **The demo** (`src/lib/mock.ts`, "Try the demo") is what App Review sees: keep it working, with acme's made-up data. + +## Checks + +```sh +CI=true pnpm install --frozen-lockfile +pnpm typecheck && pnpm test && pnpm export # export: Metro bundles the iOS app, no Xcode needed +``` diff --git a/mobile/README.md b/mobile/README.md new file mode 100644 index 000000000..ac3ae3b4c --- /dev/null +++ b/mobile/README.md @@ -0,0 +1,51 @@ +# Shipyard for iPhone + +Which agents need you across your boxes, and answering them, from your phone. +It talks to each box over your tailnet, on the box's phone API, and gets +notifications through Shipyard's push relay. The guide for people is +[docs/guides/phone.mdx](../docs/guides/phone.mdx). + +## Running it + +You need an iPhone with Tailscale, signed in to your boxes' tailnet, and an +[Expo](https://expo.dev) account. No Mac is needed: EAS builds in the cloud. + +```sh +CI=true pnpm install --frozen-lockfile +npx eas-cli@latest build --profile development --platform ios # once, and after adding a native module +pnpm start # then open the build on the phone +``` + +The phone reaches Metro over the tailnet: start it with +`REACT_NATIVE_PACKAGER_HOSTNAME=`. + +On a box, turn phone access on in Shipyard → Settings → Phone and scan the +code from the app. **Try the demo** shows made-up boxes without one. + +## What's where + +| | | +| --- | --- | +| `src/app/` | The screens (expo-router): Needs you, Runs, Boxes, a session, a run, Pair | +| `src/lib/api.ts` | The box's phone API | +| `src/lib/events.ts` | Following a box's events as they happen | +| `src/lib/store.ts` | Boxes, their sessions and runs, conversations | +| `src/lib/push.ts` | Notifications: the relay's key, registering with boxes | +| `src/lib/mock.ts` | The demo | +| `../packages/core` | What the desktop app and this one share | + +## Builds + +`eas.json` has three profiles: `development` (a development client, APNs +sandbox), `preview` (TestFlight) and `production` (the App Store, APNs +production). The push relay must hold the same team's APNs key +(`push/README.md`), with `APNS_TOPIC=dev.berth.phone`. + +## Checks + +```sh +pnpm typecheck && pnpm test && pnpm export +``` + +`pnpm export` bundles the iOS app with Metro (no Xcode), which is how CI +checks that imports from `packages/core` resolve. diff --git a/mobile/app.config.ts b/mobile/app.config.ts new file mode 100644 index 000000000..d64e93c39 --- /dev/null +++ b/mobile/app.config.ts @@ -0,0 +1,51 @@ +import type { ExpoConfig } from "expo/config"; + +// Shipyard for iPhone (Android later, from the same code). The phone talks +// to boxes over the tailnet, on each box's phone API (internal/box/phone.go, +// phonev2.go), and gets notifications through the push relay (push/). + +const config: ExpoConfig = { + name: "Shipyard", + slug: "shipyard", + // berth://pair#… pairs, like the desktop app's QR code. + scheme: "berth", + version: "0.1.0", + orientation: "portrait", + icon: "./assets/icon.png", + userInterfaceStyle: "automatic", + backgroundColor: "#16181b", + ios: { + bundleIdentifier: "dev.berth.phone", + supportsTablet: true, + config: { usesNonExemptEncryption: false }, + infoPlist: { + // Boxes answer plain HTTP inside the tailnet (WireGuard encrypts it): + // by address (100.x, which App Transport Security leaves alone), by + // short name (local networking), or by MagicDNS name (*.ts.net). + // Nothing else may be plain HTTP: the push relay is HTTPS. + NSAppTransportSecurity: { + NSAllowsLocalNetworking: true, + NSExceptionDomains: { "ts.net": { NSIncludesSubdomains: true, NSExceptionAllowsInsecureHTTPLoads: true } }, + }, + }, + }, + android: { package: "dev.berth.phone" }, + plugins: [ + "expo-router", + "expo-secure-store", + "expo-font", + ["expo-splash-screen", { image: "./assets/splash-icon.png", imageWidth: 160, resizeMode: "contain", backgroundColor: "#16181b" }], + ["expo-camera", { cameraPermission: "Scan the pairing code Shipyard shows in Settings → Phone.", microphonePermission: false, recordAudioAndroid: false }], + ["expo-notifications", { enableBackgroundRemoteNotifications: false }], + ], + experiments: { typedRoutes: true, tsconfigPaths: true }, + extra: { + // Where the app gets its push key (push/README.md). + relay: process.env.BERTH_PUSH_RELAY ?? "https://push.berthd.app", + // Which APNs service the build's tokens are for: development builds + // are sandbox (eas.json sets it per profile). + apnsEnv: process.env.BERTH_APNS_ENV === "production" ? "production" : "sandbox", + }, +}; + +export default config; diff --git a/mobile/assets/icon.png b/mobile/assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..395a9b1df9724559da3aa9218db4a399c77f4888 GIT binary patch literal 38258 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

f%0kDl#aVk|b6(BBR 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 E4^n^vBme*a literal 0 HcmV?d00001 diff --git a/mobile/assets/splash-icon.png b/mobile/assets/splash-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a3888bd10fee2491ca0025e10849ff5a02283f38 GIT binary patch literal 20880 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≈kE>_i>@bZPx^!_a$McbxR)&h3Aca&TYO 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 literal 0 HcmV?d00001 diff --git a/mobile/eas.json b/mobile/eas.json new file mode 100644 index 000000000..c7f00e498 --- /dev/null +++ b/mobile/eas.json @@ -0,0 +1,19 @@ +{ + "cli": { "version": ">= 16.0.0", "appVersionSource": "remote" }, + "build": { + "development": { + "developmentClient": true, + "distribution": "internal", + "env": { "BERTH_APNS_ENV": "sandbox" } + }, + "preview": { + "distribution": "internal", + "env": { "BERTH_APNS_ENV": "production" } + }, + "production": { + "autoIncrement": true, + "env": { "BERTH_APNS_ENV": "production" } + } + }, + "submit": { "production": {} } +} diff --git a/mobile/metro.config.js b/mobile/metro.config.js new file mode 100644 index 000000000..5ababeec5 --- /dev/null +++ b/mobile/metro.config.js @@ -0,0 +1,13 @@ +// Metro, with the code the app shares with the desktop app: packages/core +// (plain TypeScript, relative imports only) and the plugin SDK's types. +// The repository isn't a pnpm workspace, so Metro is told where they are. +const path = require("node:path"); +const { getDefaultConfig } = require("expo/metro-config"); + +const config = getDefaultConfig(__dirname); +config.watchFolders = [path.resolve(__dirname, "../packages/core"), path.resolve(__dirname, "../packages/plugin-sdk")]; +// Only this app's node_modules: never app/'s, next door. +config.resolver.nodeModulesPaths = [path.resolve(__dirname, "node_modules")]; +config.resolver.disableHierarchicalLookup = true; + +module.exports = config; diff --git a/mobile/package.json b/mobile/package.json new file mode 100644 index 000000000..6d236a57e --- /dev/null +++ b/mobile/package.json @@ -0,0 +1,56 @@ +{ + "name": "berth-phone", + "version": "0.1.0", + "main": "expo-router/entry", + "dependencies": { + "expo": "~58.0.21", + "expo-camera": "~58.0.14", + "expo-clipboard": "~58.0.4", + "expo-constants": "~58.0.14", + "expo-crypto": "~58.0.7", + "expo-device": "~58.0.5", + "expo-font": "~58.0.11", + "expo-haptics": "~58.0.7", + "expo-linking": "~58.0.15", + "expo-notifications": "~58.1.7", + "expo-router": "~58.0.28", + "expo-secure-store": "~58.0.2", + "expo-splash-screen": "~58.0.12", + "expo-status-bar": "~58.0.4", + "react": "19.3.0", + "react-native": "0.88.1", + "react-native-safe-area-context": "~5.10.1", + "react-native-screens": "~4.30.1", + "zustand": "^5.0.16" + }, + "devDependencies": { + "@types/jest": "^30.0.0", + "@types/react": "~19.3.0", + "jest": "^30.5.2", + "jest-expo": "^58.0.13", + "typescript": "~6.0.3" + }, + "scripts": { + "start": "expo start --dev-client", + "ios": "expo start --ios", + "typecheck": "tsc --noEmit", + "test": "jest", + "export": "expo export --platform ios --output-dir .expo-export" + }, + "private": true, + "jest": { + "preset": "jest-expo/ios", + "moduleNameMapper": { + "^@/(.*)$": "/src/$1", + "^@berth/core/(.*)$": "/../packages/core/src/$1" + }, + "testMatch": [ + "/src/**/*.test.ts", + "/src/**/*.test.tsx" + ], + "moduleDirectories": [ + "node_modules", + "/node_modules" + ] + } +} diff --git a/mobile/pnpm-lock.yaml b/mobile/pnpm-lock.yaml new file mode 100644 index 000000000..7544479a5 --- /dev/null +++ b/mobile/pnpm-lock.yaml @@ -0,0 +1,8661 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + expo: + specifier: ~58.0.21 + version: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + expo-camera: + specifier: ~58.0.14 + version: 58.0.14(@types/emscripten@1.41.6)(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + expo-clipboard: + specifier: ~58.0.4 + version: 58.0.4(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + expo-constants: + specifier: ~58.0.14 + version: 58.0.14(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + expo-crypto: + specifier: ~58.0.7 + version: 58.0.7(expo@58.0.21) + expo-device: + specifier: ~58.0.5 + version: 58.0.5(expo@58.0.21) + expo-font: + specifier: ~58.0.11 + version: 58.0.11(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + expo-haptics: + specifier: ~58.0.7 + version: 58.0.7(expo@58.0.21) + expo-linking: + specifier: ~58.0.15 + version: 58.0.15(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + expo-notifications: + specifier: ~58.1.7 + version: 58.1.7(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + expo-router: + specifier: ~58.0.28 + version: 58.0.28(01c662b7665e4b62efc6a8f6b7abec47) + expo-secure-store: + specifier: ~58.0.2 + version: 58.0.2(expo@58.0.21) + expo-splash-screen: + specifier: ~58.0.12 + version: 58.0.12(expo@58.0.21)(supports-color@8.1.1)(typescript@6.0.3) + expo-status-bar: + specifier: ~58.0.4 + version: 58.0.4(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + react: + specifier: 19.3.0 + version: 19.3.0 + react-native: + specifier: 0.88.1 + version: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + react-native-safe-area-context: + specifier: ~5.10.1 + version: 5.10.1(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + react-native-screens: + specifier: ~4.30.1 + version: 4.30.1(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + zustand: + specifier: ^5.0.16 + version: 5.0.16(@types/react@19.3.0)(react@19.3.0) + devDependencies: + '@types/jest': + specifier: ^30.0.0 + version: 30.0.0 + '@types/react': + specifier: ~19.3.0 + version: 19.3.0 + jest: + specifier: ^30.5.2 + version: 30.5.2(@types/node@26.6.6)(supports-color@8.1.1) + jest-expo: + specifier: ^58.0.13 + version: 58.0.13(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(@types/react@19.3.0)(expo@58.0.21)(jest@30.5.2(@types/node@26.6.6)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1) + typescript: + specifier: ~6.0.3 + version: 6.0.3 + +packages: + + 2g@1.0.1: + resolution: {integrity: sha512-+uViadKOS/wwR4pFu5g8TPn3QHpKqoX19JHCnp8k/3cLpImdcXozwvZA6Q/5PeW3AcU8neL8faaMidBcv7o8CA==} + hasBin: true + peerDependencies: + typescript: '>=5.8.0' + peerDependenciesMeta: + typescript: + optional: true + + '@asamuzakjp/css-color@3.2.0': + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.29.7': + resolution: {integrity: sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.29.7': + resolution: {integrity: sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.29.10': + resolution: {integrity: sha512-/YY9soQuWa8TURtHXHT+GbklpbAA+dZErxFGHIr6qgDg96xuGWrTAs1+MfjgVJPF0YLQsOVsOYs8lhgsPbOinQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-define-polyfill-provider@0.6.8': + resolution: {integrity: sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.29.7': + resolution: {integrity: sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@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-optimise-call-expression@7.29.7': + resolution: {integrity: sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.29.7': + resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.29.7': + resolution: {integrity: sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-replace-supers@7.29.7': + resolution: {integrity: sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.29.7': + resolution: {integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.29.11': + resolution: {integrity: sha512-snZbO7MEDOof+hvNa97EjEY7qD7h2kwvQr5AJC3ZhQudKW5dnej6k3kP9NQV88hJwaS8vDqRLFo9rivLEhle2g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-wrap-function@7.29.7': + resolution: {integrity: sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.10': + resolution: {integrity: sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.11': + resolution: {integrity: sha512-OZ6+oaK7GMyg3IfCpj8JOmn8n+w2rJbDT0LLfVDTLb1ZFeKDh3AiNELgCMUw175IJHSkLl74hG0M0VLsvx+gag==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-proposal-decorators@7.29.7': + resolution: {integrity: sha512-EtU0Hi3GvrTqD56xKmZvV/uCXK2ZbwVNPNLAquVItcAZpUhkXwWlo3Fmj0c2LxgSf2I8IDULeAepwNP1OefLXg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-export-default-from@7.29.7': + resolution: {integrity: sha512-p+G5BNXDcy3bOXplhY4HybQ1GxH3i2Tppmdm/3epyRu2VgJJZuUlZ61MqRTg582Q7ZLBdP7fePYvsumSEkMxcQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-decorators@7.29.7': + resolution: {integrity: sha512-9MTTLbF39X6sqM92JPEsoI7++26hjZvzkxKZy64aMhWLH2mPkJ/Q3AV4QLmls3R14FpSpkOwQQfUh962JGQxxg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-dynamic-import@7.8.3': + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-export-default-from@7.29.7': + resolution: {integrity: sha512-foag0BB37ROhdeIX9O8G0jX7hw0UekJc04cHMrYLOnrErsnBKqJGHJ8eDRpoCFZBvEPPygmmtw4qyU97qa4oOw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-flow@7.29.7': + resolution: {integrity: sha512-ajMX6QPcyomotqwpzhkYGxcK2i/us0rs1Qo9QvUpa+Fca0FTmqrzKrctoIYLMxcOhGZldGT/BAVkRGTWBiR8gQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.29.7': + resolution: {integrity: sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.29.7': + resolution: {integrity: sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.29.7': + resolution: {integrity: sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-arrow-functions@7.29.7': + resolution: {integrity: sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-generator-functions@7.29.7': + resolution: {integrity: sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-to-generator@7.29.7': + resolution: {integrity: sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoping@7.29.11': + resolution: {integrity: sha512-iARF4jjHSM0v8DImCACPXrwEltBP3DgqDpXTvjAMBAVpyEY0LiGss78wvI+KtmW+IJNEvZ5sOhPDCsOsXsIybA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.29.7': + resolution: {integrity: sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-static-block@7.29.7': + resolution: {integrity: sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + + '@babel/plugin-transform-classes@7.29.11': + resolution: {integrity: sha512-f8kTDM/nTvpLeafb+TJ4jboFr/Y3BbC+QzgPpPGzSKJqWLnj9LW0WLqv4XKA11LX5sr+EgvLE6Ix3YsCEusodw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-destructuring@7.29.7': + resolution: {integrity: sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-export-namespace-from@7.29.7': + resolution: {integrity: sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-flow-strip-types@7.29.7': + resolution: {integrity: sha512-wRHeUjUjCZnMHmiO5bRgjFLcoEh7JyTdByOW11ahhwNa4V0bmeGEaIvt51yq0zQp2yWIpqfxXXPyUP6GFJZHOQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-for-of@7.29.7': + resolution: {integrity: sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-logical-assignment-operators@7.29.7': + resolution: {integrity: sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.29.7': + resolution: {integrity: sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.7': + resolution: {integrity: sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.29.7': + resolution: {integrity: sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.29.7': + resolution: {integrity: sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.29.7': + resolution: {integrity: sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.29.7': + resolution: {integrity: sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.29.7': + resolution: {integrity: sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.29.7': + resolution: {integrity: sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.29.7': + resolution: {integrity: sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-display-name@7.29.7': + resolution: {integrity: sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-development@7.29.7': + resolution: {integrity: sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-self@7.29.7': + resolution: {integrity: sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.29.7': + resolution: {integrity: sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx@7.29.7': + resolution: {integrity: sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-pure-annotations@7.29.7': + resolution: {integrity: sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.29.8': + resolution: {integrity: sha512-0UpIXPtdDtMXfnV2OJAVMLpj3H/92vmkA6lpSRakmycJvj3VUy6Xs1dM8tXRugupykr5WB+LpiVl0J8LMVg2mg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-runtime@7.29.7': + resolution: {integrity: sha512-xmAscdE/AsqRW7vutbPNoUmu/nF5SrLKPs7aoJgEjo35lLKA/Bc0i2rMv/hr1+Y0o1bQCiVtith3u2vdgRL39Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.29.7': + resolution: {integrity: sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.29.7': + resolution: {integrity: sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.29.9': + resolution: {integrity: sha512-FFwIwzU+7SCOuxxV4YtJql6T9981ZVTm+FHO5GhVsRqCTdy0WwrEZh3l42ARpXruJUDGOptdduHW6Zr7pNPLNg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.29.7': + resolution: {integrity: sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-typescript@7.29.7': + resolution: {integrity: sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.29.10': + resolution: {integrity: sha512-NpugTzbKgGrNe45Ui32cN8vCFFMxVtP/9rtfwv0nP5FRDAjvYBxJcLVpYA9mr1jxP6cnIT7x9LUzuDTbWYYNRA==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.10': + resolution: {integrity: sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.11': + resolution: {integrity: sha512-WCsemW40Cpc6gouC1SrY6PBaZ+oLRlEVY9XBvZBI7il/HyUrb2nJ505wE1MHEFyDZNnrWDEuy4jL50WVHfTTSQ==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + + '@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.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + + '@expo/cli@58.1.17': + resolution: {integrity: sha512-2WKvwrq9Sr0jj4vFVt7dPtbHoxFzaSp4s5Bsk1FDmCQjZhQlWZjb7j6igBYCs0nBzZZ4UyBdSMY2hwmDhRmPQA==} + hasBin: true + peerDependencies: + expo: '*' + expo-router: '*' + react-native: '*' + peerDependenciesMeta: + expo-router: + optional: true + react-native: + optional: true + + '@expo/code-signing-certificates@0.0.7': + resolution: {integrity: sha512-zP0tnfqrFFRL8INtOaQ6XwEYfdIpIH9vrEo7y0bHQGQa50z4/QWXE5CI4nRUHxqFW4MVWOwXFg1hom1aAZHNkQ==} + engines: {node: '>=22.13.0'} + + '@expo/config-plugins@58.0.11': + resolution: {integrity: sha512-lenBm4ajWMPW+Hol3xiHHoSZEO/mA3T7X/NU3XNqm96XepwjXh2CMpIvROGLoh0amfVEIXIW3Qj3gnDS3cK/nw==} + + '@expo/config-types@58.0.3': + resolution: {integrity: sha512-wyfrwkTT/hQHzwyqkXkngKxoOa8L6ovsTP4h/UukS1mTmssee5et6HOPoN5RtawdJPnm5JO28f//C/wXlpka8Q==} + + '@expo/config@58.0.9': + resolution: {integrity: sha512-rN21dSqt6jfzpnVaBwCZVIvRFxoWEit+11AY+dSyaVkkwFWnVga0KOkFTQydtYgIZmP/vdm4QJhKeQkoUf4oMQ==} + + '@expo/devcert@1.2.2': + resolution: {integrity: sha512-wz1YedXwdNbYqk/PRr34vixnuw1+l6uSwmPXUj649cot5iYNccb2zIOnK7Nonb1Pfd/dxAY6CvU6KM3uSdxC7A==} + + '@expo/devtools@58.0.2': + resolution: {integrity: sha512-WBj/K+vv8JPSmY70ennL04YYOHkpEsGGkfuVY9lfv4XO7Qhbt5qz4q6W7maME194I5oGcimRMigUFfWNkBe90w==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + peerDependenciesMeta: + expo: + optional: true + react: + optional: true + react-native: + optional: true + + '@expo/dom-webview@58.0.2': + resolution: {integrity: sha512-bLkREoP7qL3rEuzxP60xG+TjdPoGjbnZfxkvYo5imJxGWfKMOf7x962W06Pu+WWAr4gcDRk16iA+Clg8D0zjCg==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + '@expo/env@2.5.3': + resolution: {integrity: sha512-dBGu8BAfvUcXvG4HvYth+EhcHEsdC+/fT6HTH/zFvvwfp50LG6uzpzT8TXObwEq/t2B/rvAMV5OolxQ46LWXHg==} + engines: {node: '>=20.12.0'} + + '@expo/fingerprint@0.21.7': + resolution: {integrity: sha512-rE9QN4TXGZxS3PC1yW77D1B6JNnuv3n7hXVUZxFEDDndPKFnQPC0XkqFyIz21oXbtrvThROCbV9CDVJiycCntg==} + hasBin: true + + '@expo/image-utils@0.12.6': + resolution: {integrity: sha512-AWzD/c3mM/a+sDbRgOSNzBpkUW8sUVUFcwnZ7xqkkhc5Hi9Fms0pDGw24JLxccgA6cC6bbJ8sZiQbnXBf75onA==} + + '@expo/inline-modules@0.2.8': + resolution: {integrity: sha512-7x+mbe6/rWCD6iWSPl8s7Jipdr+Ss9f6raFdHSl8oIouSL09pszJb7bD15oLje6AkioFVe/lgq/QOqKB7w8bWw==} + + '@expo/json-file@11.2.1': + resolution: {integrity: sha512-UPhKoFCj8BcwgLB1rKQ1CuR/REITnZLiqxHEHOeH1tPsdXcHGtUDh0P5bLbr7oU0nKVdtJ5rzyKx8jniMQdESQ==} + + '@expo/local-build-cache-provider@58.0.9': + resolution: {integrity: sha512-C1QZ4GDljraOtARoZPvImxA9gKLd9kb/w1fRpc+x2sCZ1qXxWmqoVh+ISuwe6niB1BvzBEDA8KH0QQJj3r9nLQ==} + + '@expo/log-box-utils@58.0.2': + resolution: {integrity: sha512-My8Lwe9FU/yDwwzqwi5LN2rzzDcJqIAZKrD9f0XHZEKz/FQnWJYdt1rsV7+RwqMGeGq2XsxTCVT1ggTCOvumxw==} + + '@expo/log-box@58.0.13': + resolution: {integrity: sha512-Cl9qc77nWjQVivUI5/OCPSEP8s20EtbK3Ivy5ayy+uHO0Cf+XatatWfTvKiHO38VOpT2ywlROzZb4XZyxZUZ1Q==} + peerDependencies: + '@expo/dom-webview': ^58.0.2 + expo: '*' + react: '*' + react-native: '*' + peerDependenciesMeta: + expo: + optional: true + + '@expo/metro-config@58.0.19': + resolution: {integrity: sha512-z8tOnyiY5jg2sbrCAD60N+G9AX6sZQyMrfrhL4DK4pkwyt5TODkxk61G0Y0k9RidXpvjguqftB7v/w8UK5wCGg==} + peerDependencies: + expo: '*' + peerDependenciesMeta: + expo: + optional: true + + '@expo/metro-file-map@58.0.5': + resolution: {integrity: sha512-Y2w8qKklLffZie28In4WF6f6e8nIJOhU0mZ5UaQdCiITVQm2a5teNdIDudEPkBsh8ItlvyHZt9n42PN2onRbkQ==} + + '@expo/metro-runtime@58.0.15': + resolution: {integrity: sha512-csALn54hZUkHFM3FofWlU5MQcJB62deCt+JtHOhQogRT+k/VTtTuhLQCrCUOtO2MAUsyhrcRRa6Nh79e1bkvfg==} + peerDependencies: + '@expo/log-box': ^58.0.13 + expo: '*' + react: '*' + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + + '@expo/metro@58.0.0': + resolution: {integrity: sha512-PMD640ihB0C3Oqm0AnDVJ/8qF2cKbRUEqGuSOr4tM/OTb9ktxsQqsiSSSeaOEgdCZBq20AxRS0d6WHNhhH2P+g==} + + '@expo/modules-macros-linux-arm64@0.27.1': + resolution: {integrity: sha512-8bwGkFZ5FaLzSXe37t8ksw4GJ7flvRhBSmmFfkZlETjm8nAPrU5D+VF8YkSmRUoQ5DA3PWLLwnYK+WhvzJ0+fA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@expo/modules-macros-linux-x64@0.27.1': + resolution: {integrity: sha512-63BZcm/aWPNe4VC9jBxKOME7abiM6rCdn6NiZTTmlEMWmBaoRWJEKj16tT/Gjkf25y9+dMwadQ9B+LNMbh5nPA==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@expo/modules-macros-win32-arm64@0.27.1': + resolution: {integrity: sha512-BcIJibqB7YxuUTf7R7gk2gbPYr6ngM0t+hTeoAhpsgS5xUlYU/TVjgrYpYOFTyYfWwgnDUv75WrJxbvVolK5xQ==} + cpu: [arm64] + os: [win32] + + '@expo/modules-macros-win32-x64@0.27.1': + resolution: {integrity: sha512-jguCWgOW2dcLY7VaReBCxU48FBX1g4DhzETm/DpD+WwxZOweiBRSwk7zaOTiTG2rifBYu4y9VYHxHrONHfOLBw==} + cpu: [x64] + os: [win32] + + '@expo/osascript@2.8.1': + resolution: {integrity: sha512-SCi+6q6uOkGhiAn6AIP/OPFgaIq/iKD2oYpnAOg2rShHStJ8ey7wyT127RbOaZXmlcY/62rHOX1WiiMnD8u/BA==} + engines: {node: '>=12'} + + '@expo/package-manager@1.14.2': + resolution: {integrity: sha512-sftl0eRVVCarI6grMdjAB3jX2pX1Mt3cdSnajlXS4QyeDkaKRM/ntBy6dcagj1VL0+cEfEqctlyvinmlZdNubg==} + + '@expo/platforms@58.0.1': + resolution: {integrity: sha512-KtLrtAvpShq16l9lTxd2fZSjULxcGxXrJTHA31iUVqrc+Af7aTAJW4ZB3yQBgi/w+kSb6BB/CG9RXI0ohbMm6g==} + + '@expo/plist@0.10.1': + resolution: {integrity: sha512-nuNOqj+r/hGJbZ1Ax3jUpZaOB8UAMHUrISALJEUKaCieTflYj7224EqFWmMpriCGk9wXS1gH+9GGVnSj0tWzuQ==} + + '@expo/prebuild-config@58.0.17': + resolution: {integrity: sha512-QSMM9YiHQnRENUIgP7wgZt71WKPLUMLz5QFm4KWA2aa20a808F6b+HV/ZzfX47MWWt39RjyT9pUcLv/dgEp0UA==} + + '@expo/require-utils@58.0.5': + resolution: {integrity: sha512-14dGubYUBmJjK9aqVSGnwSDs9uaxfzvtqJugtMCEWyuTa/eIvToUbzUwpKCSek6S/hYSEYcgds23vDJhXSBpbQ==} + peerDependencies: + typescript: ^5.0.0 || ^5.0.0-0 || ^6.0.0 || ^7.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@expo/router-server@58.0.19': + resolution: {integrity: sha512-yyqiU830tiKybH6Vr0BqXbcSCdCj5+lK/MR6l/DG5Jbv3s4jXKqa8vb4QuWRO2mMvk0xUeJO7RNyWEtGF9TYEA==} + peerDependencies: + '@expo/metro-runtime': ^58.0.15 + expo: '*' + expo-constants: ^58.0.14 + expo-font: ^58.0.11 + expo-router: '*' + expo-server: ^58.0.6 + react: '*' + react-dom: '*' + react-server-dom-webpack: ~19.0.1 || ~19.1.2 || ~19.2.1 || ~19.3.0 + peerDependenciesMeta: + '@expo/metro-runtime': + optional: true + expo-router: + optional: true + react-dom: + optional: true + react-server-dom-webpack: + optional: true + + '@expo/schema-utils@58.0.2': + resolution: {integrity: sha512-w28y8SG+5ZTdDdmH2ZnCQk9wHVwGzI9NqX5V4urJUFEnxbm7I129fJRkb8RIAJmMA1WKU5h3ONmranV473uaXQ==} + + '@expo/sdk-runtime-versions@1.0.1': + resolution: {integrity: sha512-kvisefkhxu8Fm/4M8G6DEqUaigrXfrSOm2lFw7hsk/nq0zchcp6B4wSk8rlheHY8FRi5iHxKtoVMGY/3M6h04A==} + + '@expo/spawn-async@1.8.0': + resolution: {integrity: sha512-eb9xxd/LbuEGSdua4NumCu/McVB9EM+F/JxB9pWgnERw4HQ9XyTNH1KapG6oqLWR8TuRK2LQfzJlmNi94CVobw==} + engines: {node: '>=12'} + + '@expo/sudo-prompt@9.3.2': + resolution: {integrity: sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==} + + '@expo/ws-tunnel@2.0.1': + resolution: {integrity: sha512-mljsRffbOHzmSimYQbQu9h9NR3alwCCwEEouRGFL4QRTt8dNvsNtKEPa/5jHmtDLDtsh4xXsWKwzjN9BTpeXHQ==} + peerDependencies: + ws: ^8.0.0 + + '@expo/xcpretty@4.4.7': + resolution: {integrity: sha512-EbxYllZ7/ozONVZd425cm4XnolfW+AmSFT5aP7Jdno6oc3WrYQcHz2CO20z/2rwWwYgztmV2PXvYH+BQ8YFjqg==} + hasBin: true + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@isaacs/ttlcache@1.4.1': + resolution: {integrity: sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==} + engines: {node: '>=12'} + + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.6': + resolution: {integrity: sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==} + engines: {node: '>=8'} + + '@jest/console@30.5.2': + resolution: {integrity: sha512-e8sQC4pCMHPBrPX7Hk8TJr+DM5dkUnImSTNag8SEWFAFAF6xIz4AJvCKapnrdHnZxep4bxw4PhG+ZbimYBMyKw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/core@30.5.2': + resolution: {integrity: sha512-/jqvFWoJF7LV1a6AUpYMbMm+2yIYsHJfR474H0SCzr9k8tnO/jl9wRg6zSG6lxgf6EozNlCG4amFzWsbZSvvZA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/create-cache-key-function@29.7.0': + resolution: {integrity: sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/create-cache-key-function@30.5.1': + resolution: {integrity: sha512-5qkif//qhlbt54255O/M2JtUZNlnefOzE12bi7FlApOIYO4pqrZcAwhNCfP4jOGFubez8uoLgY9czWFjYY57ow==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/diff-sequences@30.5.0': + resolution: {integrity: sha512-OsqBjHXCn8cadasoAZBP6nWYvMsRhpMzGXTpxJ5aO04NlbdhIz+FVe3q49l0AwVhsz/cEmIpBes6gAFl1/dWQg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/environment-jsdom-abstract@30.5.2': + resolution: {integrity: sha512-8/P+8hKv7L4mhFoB6gpYLj/fuzXk8PWrde7TDHh8tJz5pE1ktlMbg0y6hDY/V8MfAnispFlPl/vPifowLy3JGQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@types/jsdom': '*' + canvas: ^3.0.0 + jsdom: '*' + peerDependenciesMeta: + canvas: + optional: true + + '@jest/environment@29.7.0': + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/environment@30.5.2': + resolution: {integrity: sha512-nwFPOUMbmsjNNRCpnJpB9HbSZu4C07wDDds++5j+j1MezzPLxMPDdbdUVjr2o4RULDOValnDd70taPFI1EtxAg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/expect-utils@30.5.2': + resolution: {integrity: sha512-d/HOLSrJUlBIl6n3LzOa7cjW3xdePm5H5gQw2lixZ/0h157l9sw3mLblzFqnPcTbhDzhRQdBOX3A3KcG73nm5Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/expect@30.5.2': + resolution: {integrity: sha512-2E+1Pg6jJxbRjLNLpciC71iri/3qsKJL222/aXJEFwC0VdUSvfS+JZQQLEVjUYYc8t8pQu2MGE3cF2+bNTYRsg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/fake-timers@29.7.0': + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/fake-timers@30.5.2': + resolution: {integrity: sha512-GKk0h0tKT5SpDPxDhPg3r9mm5s8/YCBzVNMOGdRiQXwUiMsjU10mVPlMaQstH6/cu50vOb8N9oQUMETHuwwxKw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/get-type@30.5.0': + resolution: {integrity: sha512-9/2VUPitAjmBzbvDvqrxmvB7BzWsBW0WmkkojX1ODuxX1NLGxx9gfaZpHB0z8DtJ9uhGNmZG/VXBhf8uO0OV8Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/globals@30.5.2': + resolution: {integrity: sha512-62zfS+dL+M5aTNHXCNLyqD+j4oqxTIzDYrZbpqMP8Yn+gvlAGyzC6BSPNb1ZmFOakV1RtFYX/O3FCQXSWmQdgg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/pattern@30.5.0': + resolution: {integrity: sha512-HdNQYSdRTEBNrginaqzQtTjG0HRMfrra/z6Ok7uL3S87vSlarIVohEsJsSj5edu3MiHoHjAkvPROz5ZjoKai+w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/reporters@30.5.2': + resolution: {integrity: sha512-ev6E9iG73twQcfAfoTnviuYkr3yOrYbzAtMFCimv2fxHXPIp9PBt2u1wNMt0aYWgl8FPwIcS8oqRJg6alnht4Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/schemas@30.5.0': + resolution: {integrity: sha512-/hunigyNpc4RCjC0VaW3f5RCUZVM2+WQ65qP7z083Gmvac7or2LI50XVNOtE4YPgBpV0yxYiAgorAPGniCoJmg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/snapshot-utils@30.5.1': + resolution: {integrity: sha512-V3wnxNtiVmw5PPVg433Cn3VdXnsOeu/ofLw3KC04Bn2y1wIlU5kozXQn48rhrgj/02LrCVtntTEF1yBha0XSUw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/source-map@30.5.2': + resolution: {integrity: sha512-c5CehvkbfHX6yyNg7bMn2ylqlp9AHXuZ/3hPH/Lh5bxD/vefd/lV9HBjMqXef9yQNqkdwyZvkLSVSwB38hy8Qw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/test-result@30.5.2': + resolution: {integrity: sha512-eO6YU5rsLfs60ne694e0IAmRgeBnoA8mu0nlxXDbl/1j5km0o2vO9/VbbUIKIH+WRKKEI+ELgwraRGn2Lhep8g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/test-sequencer@30.5.2': + resolution: {integrity: sha512-bmij8jZyYAC47ExT2GeP7PcrlwSNS+Bp3KeRuBH88gpcxqDv6fljN8PemS4J/lLZ79xb6mpaennQTTq0zUAVVg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/transform@29.7.0': + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/transform@30.5.2': + resolution: {integrity: sha512-LBGwmaE886C41jDZ65eqR1YbXM7642MK3ZhTowZd5+xDlrDLuf4ePuDdDmVSvcr8NTVJ3MqxLkMbUCzuigUaoQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@30.5.1': + resolution: {integrity: sha512-LvVYn83nnXPl+Rg98nvcFgjx6nRMTArhSn6RAX/w3ELn54S8A42TYZvsCMdGUqTM8S0wyXbtlQdU6Hi6dykj9g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} + + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@napi-rs/wasm-runtime@1.2.6': + resolution: {integrity: sha512-mRyDmEw9/fCDXCGfL1sbgIw/GUK0PVxRW4YwgPN61F3LQ+fSyoBFarJVzgGyhF6kRzEQZ0FejDqm4WLXSeqQmw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} + peerDependencies: + '@emnapi/core': ^1.7.1 || 2.0.0-beta.2 + '@emnapi/runtime': ^1.7.1 || 2.0.0-beta.2 + + '@noxcturnal/noxcturnal-darwin-arm64@0.1.11': + resolution: {integrity: sha512-tqvZOVmSoiJzm7QjQ+whPxCP45J2C1zCAZnzc1HhwmJrFIWw/qyA8o9Cup0aVqnjNVAN+as9GHX+DbAmkCbGlQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@noxcturnal/noxcturnal-darwin-x64@0.1.11': + resolution: {integrity: sha512-V2HXkK5iKFBSc2GmeZE2I2wGxBc0kMQUHxxIUBSjuO8enKIby6cEQj8WW5EAuIli622Sqw1V7f0IIz8mXB4M9g==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@noxcturnal/noxcturnal-linux-arm64-gnu@0.1.11': + resolution: {integrity: sha512-Vf9Qbke9Hq5ToFt88XicQN0FJJuepOnPKspcKDICeYYXS2b5wQnU7uhf33QWzr1KPQhn0L0IWUCwBNhMVn6E6w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@noxcturnal/noxcturnal-linux-arm64-musl@0.1.11': + resolution: {integrity: sha512-HlwlrcfBE7JBiwWaq32R8eN4APJHQCDoQlapeK+t0wxY9s9YDMDtAnG+v7RrEz05nu7Aci21x/s8qIAA5jE+NA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@noxcturnal/noxcturnal-linux-x64-gnu@0.1.11': + resolution: {integrity: sha512-kIzTkH4rEIn8vFl42lzfK8qmKaXMwHM7txbI+XkhYKjS+2WV08yslBpwHaPGtGLXPEfx+xUTUgY5K3KVET7HKw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@noxcturnal/noxcturnal-linux-x64-musl@0.1.11': + resolution: {integrity: sha512-KpC0H+v+y/v0j4EmGiopzZ2OKo01JIBrHTjTi+veYAhZbpUfwZfShdTTHEj5OjdQ5VgaJU8yaBXmX48jgAACOg==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@noxcturnal/noxcturnal-win32-arm64-msvc@0.1.11': + resolution: {integrity: sha512-Q0Q0ll/qPzakp/GBmVDB/XthqyCkfM2CE5gZ78t9Ix/bkZDe5O0G7OyNkXRsGu49VcorxoGbBgSyF6CK+OaYlQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@noxcturnal/noxcturnal-win32-x64-msvc@0.1.11': + resolution: {integrity: sha512-as4HUwZkQegCcGoFzaLzlZbBqdx8BGgFhAoQsTsdJCUbNTxVH0f3R/AcRLOUJ6odfko0E2SSuJc70FI0zQ/IDg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@oxc-project/types@0.154.0': + resolution: {integrity: sha512-KYOUGQFlLWR+s4QMV2Q9ko38TZm7EdO87Qm7rvZLqk/webse/cDjtyxKhg/47l0byCbs/k46LT8qc4PKjAikzA==} + + '@parcel/watcher-android-arm64@2.6.0': + resolution: {integrity: sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.6.0': + resolution: {integrity: sha512-Y3QV0gl7Q1zbfueunkWIERICbEojQFCgpyG7YqOGNFLsckXyI1xu9mAIUpKY9QBYzBtSkN8dBPwd3yiAO9ovMw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.6.0': + resolution: {integrity: sha512-Ohv6OpzhUfKYD7Beb8kDvG0jbIxORCYY1JRdZnaBtnjjkJxgD7ZVL0nw2sCYd0yTMKTvz3nnTnOF3cDifK+kvw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.6.0': + resolution: {integrity: sha512-5HmXvDgs8VK+74jF9y9/2FE3/OnlcKmc56tjmSrEuZjpSZOGL+fvAu+HKJBdPs9uwoP2hE6TlSUpXZ/C5jUFmQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.6.0': + resolution: {integrity: sha512-Ps/hui3A+vMbjdqlqAowK2ZL8+BO8dBjxeWXj6npTBs3jx4wWmbPpaLuqwrQrSqIVMCnpWo238bJ1U37GhQOYg==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm-musl@2.6.0': + resolution: {integrity: sha512-9c6AUHgHoG+IY88MRIHupztQiQnrbqHYQjkM2btA+Bf/wQnQMuiD0Wfk1EVv3TlNT3x41uU71rn6E4xh/+zvkw==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-arm64-glibc@2.6.0': + resolution: {integrity: sha512-yHRqS2owEXe6Hic9z6Mh1ECsCd+ODVOGvZDyciqRd21+v+o+DnXMOrw50DSpIG2sb8GPEaPPmfeCAWKPJdq46g==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-arm64-musl@2.6.0': + resolution: {integrity: sha512-WhB2e/V7rqdHHWZusBSPuy5Ei8S6lSz6FE5TKKQz5h3a0O+C+mhY7vxU9b/stqvMb8beLnPY82ZrFTLKs+SrKA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@parcel/watcher-linux-x64-glibc@2.6.0': + resolution: {integrity: sha512-ulGE6x6Oz6iAwg75T8YQSoguBWasniIbX+QWpaYPcCnDOpdWX3k+4xbEYPZVLxOuoJI+svJJPD3sEj8G7lrQ3A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@parcel/watcher-linux-x64-musl@2.6.0': + resolution: {integrity: sha512-tkBYKt7YQrjIJWYDnto2YgO8MRkjlMTSNoRHzsXinBqbLdeOM3L32wPZJvIZxqaLMfSlS/4sUjH/6STVP/XDLw==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@parcel/watcher-win32-arm64@2.6.0': + resolution: {integrity: sha512-gIZAP23jaHjGWasY/TY6yL7NHFClf0Ga7FN+iINvk+KN94rhm94lYZhFsbYFNcA04/onvGD9kKmiJLJB2HbNwQ==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-x64@2.6.0': + resolution: {integrity: sha512-cA+/pXV2YkfxlIcXOQ5fSWqAzzPyD78/x5qbK/I0vUkrlYHA8TIz+MXjAbGouguKVSI4bOmkTSJ1/poVSsgt+A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.6.0': + resolution: {integrity: sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==} + engines: {node: '>= 10.0.0'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.3.6': + resolution: {integrity: sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==} + engines: {node: ^14.18.0 || >=16.0.0} + + '@radix-ui/primitive@1.2.0': + resolution: {integrity: sha512-KABY+VMIRPJL+Vyzv/335FEhXXD/xDv8BMb1kl48/aXJZMH0LtHCTx5ga5RnxaEP3nZHtmTLf1P9vanmFX46bw==} + + '@radix-ui/react-collection@1.2.0': + resolution: {integrity: sha512-+yiQzqcc7Sy7/5s0jrMCjpPRFB3538VNrXPWdTLZhE/SCfgEws4aI6lHWN/vvcnyhHndROWBzqmqB4QBrITZ9Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-compose-refs@1.1.5': + resolution: {integrity: sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-context@1.3.0': + resolution: {integrity: sha512-v5AYEocMISkbJ+1fTXzZpiFv7NRr3D2WiYbLIKf+FkmJ8VkP6d503eV2n34MFussHXY1pcoq3yfJiQH77dc4Mg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-direction@1.2.0': + resolution: {integrity: sha512-FtRA52a/r+LKStFT+neLUm+8vSe7wbzkbQGGeU8ixFiwC8NU14Evoq9ATECqL3eGbcUzJR4fyfA4KkK/q6dfqg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-id@1.1.4': + resolution: {integrity: sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-presence@1.1.11': + resolution: {integrity: sha512-Z7/atlkab36Z8hm+V8zYc79r0W+tiOB1o0tun1By94JyadkekLQmtEAnBSP9XKXBNQsStoStS4+gX10JpS5akA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-primitive@2.2.0': + resolution: {integrity: sha512-HCTSPMNqv55Qk0IX4geJbpyXazmqulcimwuyjxTkKi29v+QZbG2Zho9BnbBq4YS2PF+KlNb2CXoLz66uUmblkg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-roving-focus@1.2.1': + resolution: {integrity: sha512-UwraORzVUeEPMclhO1p0vz0qI+TbdDLO9i+FiOqhJyHKwdpCRCck9yVEscUnAMIzCiuNoQa8D4A9bIpOPXGt6Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-slot@1.5.0': + resolution: {integrity: sha512-tyYd9ddPXAysAbdbD9eYxgwpCSv6f3PncqVSNKQFSR5lcJVLz3cb/pANDoYrLiHBpXv7skortyUgGUWsYuPPFQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-tabs@1.2.1': + resolution: {integrity: sha512-hRoJlode+hg5ZNlR+3tkfkUliIybdTpD5lkAvHQ9yaXseGf7XVO9Ib2GPEIOuaJJbo7YWYbNpDDRfo8Dhf6/xA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-use-callback-ref@1.1.5': + resolution: {integrity: sha512-Y5GBf4NKeADoXI1geiMlMuMoURT3k9MizzzKhGb/m55H94aGigZ01PIpkvsO6lML13BA6XYAXSJ6gza7vTn5nw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-controllable-state@1.3.0': + resolution: {integrity: sha512-TAcBI7bw2ljYCbv4+zuTSd6zICu8pRt6SDN2vJ/Z06K2MXh6I9WYFe/A9ovlFDtR5HVHGm5iDxDoABm/++dbKg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.5': + resolution: {integrity: sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-is-hydrated@0.1.3': + resolution: {integrity: sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.4': + resolution: {integrity: sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@react-native-masked-view/masked-view@0.3.2': + resolution: {integrity: sha512-XwuQoW7/GEgWRMovOQtX3A4PrXhyaZm0lVUiY8qJDvdngjLms9Cpdck6SmGAUNqQwcj2EadHC1HwL0bEyoa/SQ==} + peerDependencies: + react: '>=16' + react-native: '>=0.57' + + '@react-native/asset-utils@0.88.1': + resolution: {integrity: sha512-BLb5FF7NgggGYiCsA7KKkK2qFhn0K+6iGXOI+4Ucd+G7Robzw9Gt4WsWwxLt+Od+G+/hyqfz8ASokyWFZ6VcLw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/babel-plugin-codegen@0.88.1': + resolution: {integrity: sha512-2r7aeE3dXu3hawHNYHgazWQl9MJNjcnA/gxLApFK2gPMxBCLiQOHVUSaemDQz4mKPs5svulbhtDehxo6LzTzpQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/babel-preset@0.88.1': + resolution: {integrity: sha512-tnacL6tECmtFyBf59tI1GuadSvpm/XCcRQ1vMkL3qoQECpgMVdCfhw79A6l7iZdKM78TcZ0xKV98kZlERydwCg==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + peerDependencies: + '@babel/core': '*' + + '@react-native/codegen@0.88.1': + resolution: {integrity: sha512-URPgPhnsxqeQSLyTRVzhZZ8iNXtZdR1Jop6lqaQacymvl3byghXisNIRR1YyG6PbXUfzPan5Jmz/kPhUUsZ2Yw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + peerDependencies: + '@babel/core': '*' + + '@react-native/community-cli-plugin@0.88.1': + resolution: {integrity: sha512-L2CQvzsOMz4oof6AVLSzesFL1Q92nrtXpK0uQH2VwdOmzzgkiHql8WFQSo9VLvMFGJDg8+G6enrHH573ruqqWA==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + peerDependencies: + '@react-native-community/cli': '*' + '@react-native/metro-config': 0.88.1 + peerDependenciesMeta: + '@react-native-community/cli': + optional: true + '@react-native/metro-config': + optional: true + + '@react-native/debugger-frontend@0.88.1': + resolution: {integrity: sha512-4ZjH2093hZWWgsYs5ExqjzJX5uCS4R5yZa17eRHsQClUc6RjlV61kLdIk722sQReLL+NYtBn2RJtdcQtLCwiug==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/debugger-shell@0.88.1': + resolution: {integrity: sha512-vrOLlxkp/417qcSUiS3x3gmdoQHYA/26oEKIWPB4EekJG0uJxKXsMR0tHIDiJWO0JH/2BO3M+507DjR1U74jQg==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/dev-middleware@0.88.1': + resolution: {integrity: sha512-0smOWE3NCdEYUwPiEdiwVXjTdvXcwSejviCM0YZB0Dj6HaQ+uu4hpSrvgERDevr5dvtSaqr8N4TdYZCLXiVgFw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/gradle-plugin@0.88.1': + resolution: {integrity: sha512-zalxoJJ/m5kxLnBy9I1zYrx4jaPxPXdys8DeROvrSOa3pSQkTwVVXRZ4FkXCdGodVA9KR2WitplDo/URNjyvFA==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/jest-preset@0.88.1': + resolution: {integrity: sha512-ue9L2ejEA+i176kz1uadJah75orz9YvP4L515yuAqqvjNNSwTRSkErUsdg0hS2QbDVTx+2C/D5gMUWCirLKT+w==} + engines: {node: '>= 22.13.0'} + peerDependencies: + react: ^19.2.3 + + '@react-native/js-polyfills@0.88.1': + resolution: {integrity: sha512-B62O6zVMYW7kK8dxIuCwpdJ5RYcIvET6ItScm0sfsTibJs+llS0krUVSAOHnEUn3lbFMfw+o+sNdWREOAc6FfQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/metro-babel-transformer@0.88.1': + resolution: {integrity: sha512-74bvSM4lVZcv+M777/uYW2Nzs6Ga5/F0Ncn9dmeXyUPFMkJO3Ys5v9YlhI//AQ2+0nxojYYFVS/rlAjOkVjtHA==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + peerDependencies: + '@babel/core': '*' + + '@react-native/metro-config@0.88.1': + resolution: {integrity: sha512-Q0rKoC55HSOIc4j55lCOHpjIt/JkGQ66u2KsorfTC99LaRIez9UYJ/mhMwhjkZqGHq5Z4iBT6PCd4eQf35zdgQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/normalize-colors@0.88.1': + resolution: {integrity: sha512-2SAKiLyZRf+peBLkhhJWGY5vC26w1Uj9QBgUZvjAnOxjgeEKUGBE5riPS0R7+YoqSrRL0w8ucwZB4M+vvy9HMg==} + + '@react-native/virtualized-lists@0.88.1': + resolution: {integrity: sha512-Zt+OGvJE6VgmzgemZL8TSA0VomNWpHMNcG0OvLkkBQEGrzY8OdDHRfjJh7S+f+UFJF77kicRC6o6mt3A7ER9lQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + peerDependencies: + '@types/react': ^19.2.0 + react: '*' + react-native: 0.88.1 + peerDependenciesMeta: + '@types/react': + optional: true + + '@sinclair/typebox@0.27.12': + resolution: {integrity: sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==} + + '@sinclair/typebox@0.34.52': + resolution: {integrity: sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@10.3.0': + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + + '@sinonjs/fake-timers@15.4.0': + resolution: {integrity: sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==} + + '@tybys/wasm-util@0.10.4': + resolution: {integrity: sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + + '@types/emscripten@1.41.6': + resolution: {integrity: sha512-uN+9i8bFT5CUcZfyIEYDrSueACEyKGbUs5kC/72DGlZZoinh84sJfVV0i8UOJD1asdzkvLPBRrKs41kZ8MdEXg==} + + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@30.0.0': + resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==} + + '@types/jsdom@21.1.7': + resolution: {integrity: sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==} + + '@types/node@26.6.6': + resolution: {integrity: sha512-MzQj+8Kx3XI40OmUAE6Qoh58ZMNstNNMwn2nfd3qWsfe7nDNSqJNzes4njhz6AHwrSHOffSLwXU6yb474Q4aog==} + + '@types/react-reconciler@0.33.1': + resolution: {integrity: sha512-0kF59ji2mKuHUd5wytHSpmORybMYVerJvq0K10pz9ZFoOlJ3e+w1LBjLshWpCrokeyQOioRodNbO4PH4ddvRfg==} + peerDependencies: + '@types/react': '*' + + '@types/react-test-renderer@19.3.0': + resolution: {integrity: sha512-TX4p2D4Z2oigM3SXU7+QyLSUnSR0vR1S1Pfxm/qFL9nHQ3jclgi6ioGoWQmlIr1DeKRVmPJrmNlhgM0JlWlLUg==} + + '@types/react@19.3.0': + resolution: {integrity: sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + + '@ungap/structured-clone@1.4.0': + resolution: {integrity: sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==} + + '@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.12.2': + resolution: {integrity: sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==} + cpu: [arm64] + os: [android] + + '@unrs/resolver-binding-darwin-arm64@1.12.2': + resolution: {integrity: sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.12.2': + resolution: {integrity: sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==} + cpu: [x64] + os: [darwin] + + '@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.12.2': + resolution: {integrity: sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==} + cpu: [arm] + os: [linux] + + '@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.12.2': + resolution: {integrity: sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@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-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.12.2': + resolution: {integrity: sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@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.12.2': + resolution: {integrity: sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@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.12.2': + resolution: {integrity: sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@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.12.2': + resolution: {integrity: sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==} + cpu: [arm64] + os: [win32] + + '@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.12.2': + resolution: {integrity: sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==} + cpu: [x64] + os: [win32] + + '@xmldom/xmldom@0.8.15': + resolution: {integrity: sha512-/5NV/vDALVFDXgLmfsy9TRCBlKwO2LNBFzpzvb9iIj+jR+eSc6DLYYvVOdivT/jm7MtU6TebYuRmzEOI7w40UA==} + engines: {node: '>=10.0.0'} + + '@xmldom/xmldom@0.9.12': + resolution: {integrity: sha512-5AXjrcMClTryPe9LgZrygpB1lj7s0S9E0+W+AHaVKAVyHanafK86iPSvG5xHVSp/jC+VH1UXu0TAEmY279xH7A==} + engines: {node: '>=14.6'} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + + acorn@8.19.0: + resolution: {integrity: sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + agent-cli-detector@0.1.7: + resolution: {integrity: sha512-d8OWDVdZMgjhLUT9ZPgSv/BdFFF9pVuscC0JdUSz3bjwE15gcp6u/o0/JooM2yyAWC49KThFhXlgTXRa9B7yng==} + engines: {node: '>=18.18'} + hasBin: true + + anser@1.4.10: + resolution: {integrity: sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-escapes@7.3.0: + resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} + engines: {node: '>=18'} + + ansi-regex@4.1.1: + resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} + engines: {node: '>=6'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.4.0: + resolution: {integrity: sha512-KzTVk2tCWAHtYrvvvaP8bJKJq2pVinhLcGEQdtLIYPbmNGNyYe8QwNaTUYQp2J7/vIsUKt5QCqAfUkYyG9DkOw==} + engines: {node: '>=12'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + + babel-jest@29.7.0: + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + + babel-jest@30.5.2: + resolution: {integrity: sha512-ES8WeJ2fNWPEDunyAtUfJ12nHyaWUloCHdkfK2oW5uSoQSUmjNKdWiGaXJITJwvFEWoD/evHEg/QoCXAvLaQqQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@babel/core': ^7.11.0 || ^8.0.0-0 + + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + + babel-plugin-istanbul@8.0.0: + resolution: {integrity: sha512-18wCskrN3DgbuBmp1gr7LBGT8xdz5xhQQqFvFhVxbkl8VBCrMKQ2YtqBWtUal1Zrc1HTuX0011+Brjw78TCFkg==} + engines: {node: '>=18'} + + babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + babel-plugin-jest-hoist@30.5.0: + resolution: {integrity: sha512-gtGo1B+u14jrZQv6TdSWIWkTqclboo7Qn+dFAGUOIuXLFuJKAdg3U5MIWzZnW4vfUb4dX9skmAMiby86e/SF4A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + babel-plugin-polyfill-corejs2@0.4.17: + resolution: {integrity: sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.13.0: + resolution: {integrity: sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.8: + resolution: {integrity: sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-react-compiler@1.0.0: + resolution: {integrity: sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==} + + babel-plugin-react-native-web@0.21.4: + resolution: {integrity: sha512-FSclsDTGi5EcvpbW3TM7s8GLWwQqo5wI9zQqJr2m0IoJRenSkp1+bVvdeZXTNznI5Ms9Bry7DLBR+C5Shb9gtw==} + + babel-plugin-syntax-hermes-parser@0.36.1: + resolution: {integrity: sha512-ycduwJbvdvIMmVvlAZqGggS+pm5Eu4Bk9pcV9Sm2Z4PJNRVsKkv0g7vHj+LeuC1gHTeF67sJXFOq61IlqCa2hA==} + + babel-plugin-transform-flow-enums@0.0.2: + resolution: {integrity: sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==} + + babel-preset-current-node-syntax@1.2.0: + resolution: {integrity: sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==} + peerDependencies: + '@babel/core': ^7.0.0 || ^8.0.0-0 + + babel-preset-expo@58.0.22: + resolution: {integrity: sha512-2/pbzxDh4wd4MrBU4lFqFWEfCQooCVjnh6JJZnPLmWisOy5+r4qaOItcH+zaiO4hP2CyYwnyotg1QKhgsmAMEw==} + peerDependencies: + '@babel/runtime': ^7.20.0 + expo: '*' + expo-widgets: ^58.0.25 + react-refresh: '>=0.14.0 <1.0.0' + peerDependenciesMeta: + '@babel/runtime': + optional: true + expo: + optional: true + expo-widgets: + optional: true + + babel-preset-jest@29.6.3: + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-jest@30.5.0: + resolution: {integrity: sha512-ZGPn5ClP4lBDpuOK8W1yQIOy359HmbnZv3suucAlIe+SEE9yDsxV4S2PjSbH2Vc97U+WmzYD7vw3kr8NsQ/i6w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@babel/core': ^7.11.0 || ^8.0.0-beta.1 || ^8.0.0 + + badgin@1.2.3: + resolution: {integrity: sha512-NQGA7LcfCpSzIbGRbkgjgdWkjy7HI+Th5VLxTJfW5EeaAf3fnS+xWQaQOCYiny+q6QSvxqoSO04vCx+4u++EJw==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + barcode-detector@3.2.3: + resolution: {integrity: sha512-PLinpWGiOQoQH4X+YObWZ6iXeffXKDM3d4vnOD86481SvukIfvkf7jEE/tud9oI4HTDxtDdlHaFilA5Kn7Xa7A==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + baseline-browser-mapping@2.11.34: + resolution: {integrity: sha512-Aqr8mA1kIvyJ3UY5YAY7ib8LSo1DmDMbMnVqGPtsKW1LxaFQFwn9Eb3yvq2fUKJsRvaXjnAV7R5osqETapzNiA==} + engines: {node: '>=6.0.0'} + hasBin: true + + big-integer@1.6.52: + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} + engines: {node: '>=0.6'} + + bplist-creator@0.1.0: + resolution: {integrity: sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==} + + bplist-parser@0.3.1: + resolution: {integrity: sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==} + engines: {node: '>= 5.10.0'} + + bplist-parser@0.3.2: + resolution: {integrity: sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==} + engines: {node: '>= 5.10.0'} + + brace-expansion@1.1.21: + resolution: {integrity: sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==} + + brace-expansion@2.1.7: + resolution: {integrity: sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==} + + brace-expansion@5.0.12: + resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==} + engines: {node: 20 || >=22} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.29.5: + resolution: {integrity: sha512-khTmKu5NGYTotqcYo8Bew2k4RAE9PuXRSFRXG2lQBrCEQHyeQ/vX6gKMxfokwywBsLiXZMnHsmWMG1pnO8J7uQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bser@2.1.2: + resolution: {integrity: sha512-V2o8YS2EhrKMO9AumnkK0ynynfFlsajpYupwq7S46H5mhcanwxDkNTw3K67wPIcKTH1ffkA4vhMOtAc7gRmPZw==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001819: + resolution: {integrity: sha512-LFUqIIAwpzsIuevnKnsR9qnStBcgzPShTX61lBwN9uFkkf8o8zLiebEjbW8AYtZiF+1YKDWfdt/pWDtMuG8Xwg==} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + engines: {node: '>=8'} + + cjs-module-lexer@2.3.0: + resolution: {integrity: sha512-lmNyBzi6iYiqyrExTctfmjd8tInx+dHu9PBomTfH5RXS53c27JMFJgzNv5TyAnm3PgGf+MLy0+Ws41/HlVxdKQ==} + + cli-cursor@2.1.0: + resolution: {integrity: sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==} + engines: {node: '>=4'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + client-only@0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + collect-v8-coverage@1.0.3: + resolution: {integrity: sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + + compression@1.8.2: + resolution: {integrity: sha512-o8vI5RE5A6EVVOd9o41jKp41aJom+QTEO/Bx8MYNjexMo/Bv2WOjUfZr+aL0WnYSgymUy6zeguqLTsIhV0gMvQ==} + engines: {node: '>= 0.8.0'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + connect@3.7.0: + resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} + engines: {node: '>= 0.10.0'} + + content-type@2.1.0: + resolution: {integrity: sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==} + engines: {node: '>=18'} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + core-js-compat@3.51.0: + resolution: {integrity: sha512-52r6fkXgxv4GLMjmFcMWRx7X9bw071xTTdrDcdyPGRqU2oE+9pCG0bAOMifSBdLw0JRBZKEF0q3B55qPlLuE8g==} + engines: {node: '>=6.4.0'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + cssstyle@4.6.0: + resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} + engines: {node: '>=18'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + + dedent@1.7.2: + resolution: {integrity: sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + + dnssd-advertise@1.1.6: + resolution: {integrity: sha512-Ndrrf6BMPalkQPd/zubL+4YghH2J9NspapQ09uDXwYbvOPkP0oaqf5CkcwJ0b50kS2O3ul6yVu+jz+RY62Cejg==} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + electron-to-chromium@1.5.467: + resolution: {integrity: sha512-Nw9X371rtZmYcBSnEijnCDONILjs93biCZO34juC7MBOmK8E+GFnyD4T/WvyrlJkppul7oxg6TwvtKst9SODTw==} + + emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + error-stack-parser@2.1.4: + resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@2.3.2: + resolution: {integrity: sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + exit-x@0.2.2: + resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} + engines: {node: '>= 0.8.0'} + + expect@30.5.2: + resolution: {integrity: sha512-0LNuMvs8/5mRYhnCR4k+lGV7fqPMs6Bnksda4S3zsCUmdxBpAn4zU4NNzXdq1pMKe/H4W5t/zVIDSJ/H3e0vDA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + expo-application@58.1.2: + resolution: {integrity: sha512-WYFdNHGaxe/j69oYREhK0cKsKYszuIuz399WXYCP+M1grfO+FCWB/RbuMgaXJsLWlzqhNjA/zLgfJ+33FwrQvw==} + peerDependencies: + expo: '*' + + expo-asset@58.0.19: + resolution: {integrity: sha512-9tYdhiPUJKA3OjnQQJtcP4Yrdc9TPR1JQXTomcLdDSV4XgHSXRpsnp5zsIfM6S/y30QsBFHS6G3WIBaocCiPtA==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-camera@58.0.14: + resolution: {integrity: sha512-yEiMuJ2d7A+EqsP8rlGIvgaUzdk/rW9CXR6R7WKqludxU3H+JcSUbPC3ldr3ZpmaYlgXP3x+oOO9BfQy7yKK2A==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + react-native-web: '*' + peerDependenciesMeta: + react-native-web: + optional: true + + expo-clipboard@58.0.4: + resolution: {integrity: sha512-b2eEJMwdWXLTrmrkg/otsmL2OV6s9D90tytSNBsY87UswrWf6JwxcB2OaWegyUWD9XnvtBVNeVK7lej0zZh+5A==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-constants@58.0.14: + resolution: {integrity: sha512-ogn/7xLmvkEVYX6SimDkcNDn/d8qZpCTQdBWPnMI+Ry7Sfch0Dz2GIcweqddK4hrkvrSY01TS20BZfMlCpJ75g==} + peerDependencies: + expo: '*' + react-native: '*' + + expo-crypto@58.0.7: + resolution: {integrity: sha512-g+4i4UpqQ5jNy1VPRvVVvr9aIdh8WwvxbpwL2ntiSESDRsXyVSeb8JM6tHVdC3b9J2nGxjtrhrsaWOo0jbSxlA==} + peerDependencies: + expo: '*' + + expo-device@58.0.5: + resolution: {integrity: sha512-GNyaHPwoiI/z2SGR14R6d9J7hFSW2JabZieJtC3l6/LO2mJYVCbhEsQ7/1ljGBeTUnFFWHcFLccdaWEhOWtaQQ==} + peerDependencies: + expo: '*' + + expo-file-system@58.0.13: + resolution: {integrity: sha512-+/1aFErkawyky5UdWI06zYeO2DeHUnfaWnYHeiI8M8Z/sB6L66gI3WUxqtvUvKJoaM0Ti1CximD3x3JwteLYIg==} + peerDependencies: + expo: '*' + react-native: '*' + + expo-font@58.0.11: + resolution: {integrity: sha512-6r7s6xk2L2orvum+x+TY1fzEcMtuCBRQTLgC/Su2uLzNPpT4L+E+S4IAGy8ZIjeVvwk2j2pj+HiZ23O7eh1PGQ==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-glass-effect@58.0.5: + resolution: {integrity: sha512-PkL1X/r0cTs6NG47Xp3TxRvtqSeRmPYhPOHp3GDmZB2oOxpjXge6qLi/bSSv0asFWqf+MLOlXZ+hq2Imuh0Z1g==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-haptics@58.0.7: + resolution: {integrity: sha512-mAY3rbng6EuYysq9wnJKhKwYYlDjqnPYcS5OXe3zj4TlAaOFMl/EfiSOuAMawc2nsXCAnwJ5U0E11nq5zQO0mg==} + peerDependencies: + expo: '*' + + expo-keep-awake@58.0.3: + resolution: {integrity: sha512-wLRF+XeVsD/Rt/ZyX+A0mk1brdf8vefWizNAPzqV5eOCgkj23LCRZdN8gUi5X8UwyR8UJ7Y7Dzdz4YDGB/4c9Q==} + peerDependencies: + expo: '*' + react: '*' + + expo-linking@58.0.15: + resolution: {integrity: sha512-N6jmeKRsMO+DXmAH1AnStVEXK4FpL3fMzam9dJWIhd/FlMt/DCNRGUn2cqM7kNsDPSHGYGBIOCGsrW+Akp0xwA==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-modules-autolinking@58.0.16: + resolution: {integrity: sha512-YglXoBBc3QwqqFfFQD1XVfpxXdF9RkuZOVxWTn5uHPiyvXSMFiVO16GnV+VSd+njKld1EJt7vQucCsDiLp4xVA==} + hasBin: true + + expo-modules-cli@0.4.0: + resolution: {integrity: sha512-NuvnnEFL+UMuQSjykg5ZhV0oxkOww8exJbZh+75pFF7DJhE3kQtfnOd4Yq4G6PrkVnqbeuKsqf6zX8V9p65ZYw==} + engines: {node: ^22.13.0 || ^24.3.0 || ^26.0.0 || >=27.0.0} + hasBin: true + + expo-modules-core@58.0.28: + resolution: {integrity: sha512-2FCnT8mIubdQAHVtX9fVMN9qajF7hGDC3CjxxBG0HlyK7NEsxUDKkukiNVzqQpwiI+jJx7ysG0YvATwKKlu1sw==} + peerDependencies: + react: '*' + react-native: '*' + react-native-worklets: '>=0.13.0' + peerDependenciesMeta: + react-native-worklets: + optional: true + + expo-modules-jsi@58.0.21: + resolution: {integrity: sha512-6FG3jKt89s+qolbalas+OE5gQjDYu/sfV7HVAFEw3JVtkS1+MVfCvQLxp3RAm85bVNO0vgfnbn5z6A8WSDWalA==} + peerDependencies: + react-native: '*' + + expo-modules-macros@0.27.1: + resolution: {integrity: sha512-xWNI+LpK4Pdmj52ygNYlxefZDhw4mpe6s5yVCLXpqtOyU3PPrFGJJJnDyBpOsOv+mXiYLeaszEEJEpDKBObZ7A==} + + expo-notifications@58.1.7: + resolution: {integrity: sha512-sDpK0PRMt0s97h3yEAWTDqgh01qFccQwy1QljdsAGnZ93h4eBGv9SOkQohkk7LJLBOm6RWmtd5Sn03X6z0aR5g==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-router@58.0.28: + resolution: {integrity: sha512-figS9IpRn1h3iYUii1PY7ka/6XSIQ0EBKR5HqKcDl8gadN4hGfS90WFU9gjpquIdM72lS3Dxm6CT2vGQmsiQSg==} + peerDependencies: + '@expo/log-box': ^58.0.13 + '@expo/metro-runtime': ^58.0.15 + '@expo/ui': ^58.0.25 + '@testing-library/react-native': '>= 14.0.0' + expo: '*' + expo-constants: ^58.0.14 + expo-linking: ^58.0.15 + expo-symbols: ^58.0.4 + react: '*' + react-dom: '*' + react-native: '*' + react-native-gesture-handler: '*' + react-native-reanimated: '*' + react-native-safe-area-context: '>= 5.4.0' + react-native-screens: ^4.30.0 || ^5.0.0-alpha.3 + react-native-web: '*' + react-native-worklets: '*' + react-server-dom-webpack: ~19.0.4 || ~19.1.5 || ~19.2.4 || ~19.3.0 + peerDependenciesMeta: + '@expo/ui': + optional: true + '@testing-library/react-native': + optional: true + expo-symbols: + optional: true + react-dom: + optional: true + react-native-gesture-handler: + optional: true + react-native-reanimated: + optional: true + react-native-web: + optional: true + react-native-worklets: + optional: true + react-server-dom-webpack: + optional: true + + expo-secure-store@58.0.2: + resolution: {integrity: sha512-VupWWEuQF6IiQ06McSymtn7/tehs8ifThhFwAU4UK8poomZcaa2S0UVt/y7G2XozBdkI3xpiPSx+r0pS2zsuYQ==} + peerDependencies: + expo: '*' + + expo-server@58.0.6: + resolution: {integrity: sha512-6DBlSZwxk3J0y1j2s4XebAWNiwGaMp32NcWX7b2kJC2+EFf1g+pCcVmx8ylawt2tyLmbDHswm4MHOfrd4bqfvA==} + engines: {node: ^22.13.0 || ^24.3.0 || ^26.0.0 || >=27.0.0} + + expo-splash-screen@58.0.12: + resolution: {integrity: sha512-8TceS1bu1R0IuLP9VPa6cPeVytR/V/+NqhA4rOqwqDr5MIu6u4hryIxxLYWKwWXGLOzoPC6paaBiqnMsr+nLuw==} + peerDependencies: + expo: '*' + + expo-status-bar@58.0.4: + resolution: {integrity: sha512-e6JJHziSSNb1v1VSzmDrAPf6GFoPRdVOIDrTCcK3bHfbJEAZGZ3YZXfqlorZtUFDT0z6NcjaZf0mPWifJZcqew==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo@58.0.21: + resolution: {integrity: sha512-2Q8jp0fKLrDMou4aKWZ5V2cCVfcwOScuV8GBMkogiXIv7bCwwN4CIkUIq5QsX7DHXJxbruXLTXEgrp6J+iF4YA==} + engines: {node: ^22.13.0 || ^24.3.0 || ^26.0.0 || >=27.0.0} + hasBin: true + peerDependencies: + '@expo/metro-runtime': '*' + react: '*' + react-dom: '*' + react-native: '*' + react-native-web: '*' + react-native-webview: '*' + peerDependenciesMeta: + '@expo/metro-runtime': + optional: true + react-dom: + optional: true + react-native-web: + optional: true + react-native-webview: + optional: true + + exponential-backoff@3.1.3: + resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fb-dotslash@0.5.8: + resolution: {integrity: sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA==} + engines: {node: '>=20'} + hasBin: true + + fb-watchman@2.0.4: + resolution: {integrity: sha512-tGQtaoYisPDriJBN0mT5yZSyNETnJGA1gTYxaVRAE5KUO3LI9kPUc9WIu8JXcxaIci+faIKlzXqXyPgrmubtBQ==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fetch-nodeshim@0.4.10: + resolution: {integrity: sha512-m6I8ALe4L4XpdETy7MJZWs6L1IVMbjs99bwbpIKphxX+0CTns4IKDWJY0LWfr4YsFjfg+z1TjzTMU8lKl8rG0w==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@1.1.2: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} + engines: {node: '>= 0.8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + flow-enums-runtime@0.0.6: + resolution: {integrity: sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==} + + flow-estree@0.327.0: + resolution: {integrity: sha512-f9vK751YUzD0qaHSpKc5/qQM6gqOlgGS+4ZRqTNcZOpVqn3mC55yEQ6dUG2K1eaVm5FbKkz9CFWe6XNvrkQFQg==} + engines: {node: '>=18'} + + flow-estree@0.331.0: + resolution: {integrity: sha512-FVLYkSL/ITb/QXBEQvNWPjPooRGswuUtGOwrH+puSlMDneNkxy640+FZsk/TfKL+b7Wbw/Fg9FTUv2bMQDpj2w==} + engines: {node: '>=18'} + + flow-estree@0.336.0: + resolution: {integrity: sha512-0VaGWHJourzh88otU5bVJ4Z/oIsD+R6yaeR0Q8t8dezsKQI/RLi5m3fNzkiLYLhJ+YwM3JRSKlOqGplOI5Yo3w==} + engines: {node: '>=18'} + + flow-parser@0.327.0: + resolution: {integrity: sha512-/MYZ5hXWf5ozpbdfUDmazMgQXviLxWEiRLH3MppEGDdW0itRVqmB5UaU7QX+SBCDNiq+gEesSVn8nlxmPDyDkw==} + engines: {node: '>=0.4.0'} + + flow-parser@0.331.0: + resolution: {integrity: sha512-vEZcHIlnKeN8JSVtYFczj8sWJfHIJOkz+YG00O/oul/Bete+t1ZhTi+O6JRRLFYvGW+yJkZ0YgL16iStnbkUqQ==} + engines: {node: '>=0.4.0'} + + flow-parser@0.336.0: + resolution: {integrity: sha512-O8QvQf/B3rBF+eagcc9/WMAjfJoaKckdgSd8PT/qvMIIe4ZjVKrSqV5SDnRFAKY0VrE8r5C4ADYgvYhmwkWADA==} + engines: {node: '>=0.4.0'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + getenv@2.0.0: + resolution: {integrity: sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ==} + engines: {node: '>=6'} + + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + hermes-compiler@260318099.0.5: + resolution: {integrity: sha512-4Gze+pGTGTUBRmnv6LtdOMo6ZzMMh3hEkvDiWzvuNL5LM0EO5YGhr8xh3fRjFaEqReUwEGjJGcGgEPFe9+E6Gw==} + + hermes-estree@0.36.1: + resolution: {integrity: sha512-guv1nQ6IJ7S83NRFPWc3SA7IBZrdNC9kapwOq6uXvF4wP+sDCgjzQbKPCoyYmoyZRzztF/n/c36l/rccCZSiCw==} + + hermes-parser@0.36.1: + resolution: {integrity: sha512-GApNk4zLHi2UWoWZZkx7LNCOSzLSc5lB55pZ/PhK7ycFeg7u5LcF88p/WbpIi1XUDtE0MpHE3uRR3u3KB7TjSQ==} + + hosted-git-info@7.0.2: + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} + engines: {node: ^16.14.0 || >=18.0.0} + + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + invariant@2.2.4: + resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-arrayish@0.3.4: + resolution: {integrity: sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==} + + is-core-module@2.17.0: + resolution: {integrity: sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==} + engines: {node: '>= 0.4'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jest-changed-files@30.5.1: + resolution: {integrity: sha512-0+bvMM/ENhDI29Z8q1r4HxiDIi4G5tnBmSw4esfPQoj9q8Nik7KIyuxHkTVnnniJQf05SxpGaKDQ+4h28ynGPg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-circus@30.5.2: + resolution: {integrity: sha512-vffFgjs5JSJ9q4ds1vNW3klKYPJfYfIY61LT/zaZgvTeASJOWZUt8LBfHgIcV4rwxlPBLl/ePBGccHEclS4PlQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-cli@30.5.2: + resolution: {integrity: sha512-YYYxUUVjFgPvgEleKNKMaYGIFgR3l3832Cl0kRL/oCiDZ03v7wImUtquHl2OOBCCNgprjZgBN5bczS/JklPBDg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@30.5.2: + resolution: {integrity: sha512-U6221OZekabePvGcGPf4raIBKMvYQWFHvhobDJRojOYaFMj2HaGytAdknjDhYc6JTz2fdHW9+6k0wWUDaNeOFQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@types/node': '*' + esbuild-register: '>=3.4.0' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + esbuild-register: + optional: true + ts-node: + optional: true + + jest-diff@30.5.2: + resolution: {integrity: sha512-rBtHnI6BWTiWj3lM7fOLVfChx7R9B0u9VV3PRHawKs79x6ZjW1QoSrKenaigNGWlvhtoi2BqvDbABDie+Os3xQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-docblock@30.5.0: + resolution: {integrity: sha512-NwDqcxtoZi33RhuW+zJS/RVA3rmheQ8BnwpYZuc/Eruaz6seQb7+aoCeDZu/3X7W2XmD8DbSo9Pn72DbKsBFYw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-each@30.5.2: + resolution: {integrity: sha512-GRrW+7fmmgmkvyfEBqc1QFdWnF1Ex5yG6Y6AWL4TTxnkWlKIT98dsKh3P3UuWm6v4XsQwVE6DEzXIPMzWJ3ZbA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-environment-jsdom@30.5.2: + resolution: {integrity: sha512-6NOZjEP+WNi4WXjbxb/1ROnfaMxn6Dhqu6uSC22o0H28z+uppejs/jZ9KCVoLepqqoCjcNZujtzQqC9jSV15jg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + + jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-environment-node@30.5.2: + resolution: {integrity: sha512-Ciz4KgTGIbojxSKpuFImgWJj5EyqfE8xMq9NxWmOXnQywHHS03H9Mv+vaCB29J5pr3JBrY27WbRV18rBdjh8Dg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-expo@58.0.13: + resolution: {integrity: sha512-gmQUfdG83oiOSasPRP0Qp0WcEEihVBkqr3fd5kT5nHDBEH7liw/e4s0+UhdV7LoOLLtgPIgYd4ksEhdy97oWqQ==} + hasBin: true + peerDependencies: + '@react-native/jest-preset': ^0.88.1 + expo: '*' + jest: ^29.0.0 || ^30.0.0 + react-native: '*' + react-server-dom-webpack: ~19.0.4 || ~19.1.5 || ~19.2.4 || ~19.3.0 + peerDependenciesMeta: + expo: + optional: true + react-server-dom-webpack: + optional: true + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-haste-map@30.5.1: + resolution: {integrity: sha512-VIFgt67jW480YDxKfEv9IYQKrFpYt7bOCMn3VsnjK7AK9qo7p6acpnA1DHwsVOULE3dTaYew/6JaTD/d0VDHoQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-leak-detector@30.5.1: + resolution: {integrity: sha512-gt4GT2aWgEoCNTcBe4rqS74xTIUJxi+UD9SNSu9aOk5LmTEd6fS5KSTmAKAfitCCktQHNN+upUuL6EkBfFbMDQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-matcher-utils@30.5.2: + resolution: {integrity: sha512-lFkB365PTIHOhPzwrb9T6gvlDnPpOZ7/c3ewOKKB7bzztqjVrtlyRL2MkyfJXpyY2u2SKw001JKrTx14fBUFcQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-message-util@30.5.1: + resolution: {integrity: sha512-UdQlLdd9wL/Ys7xRErckqwD6wPlSZYueosSWuHc1r2ztGLwlgPvtSJq2+BPEgaEY13WLvfFbmhTj8pba0Sd1jg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-mock@30.5.2: + resolution: {integrity: sha512-KTHb37Fhj8xY8qPFvTFaFJHcdsumQp+ExsUlgoX232Agmc706gagBs53+CYvulV7MVQo9AgXOUxsqzzVBoJlrA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-regex-util@30.5.0: + resolution: {integrity: sha512-Mg0WK7A6xRHLSA1udJ8y9f3lM0uUhFTBnLKzwPmqB9AylvpleJ6BLemR8K9dK27DY+cesDryoA7yLZCAHsPG1A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-resolve-dependencies@30.5.2: + resolution: {integrity: sha512-GMI0DP5enX9Z2qW2zFy1bOkrCfWAOPRJQ7qHt0pdfrxBPsgWxglMPrRSK2TX/wRWYxcPRSLFg3Z88qPOzHx7FQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-resolve@30.5.1: + resolution: {integrity: sha512-wprhLejRtwN6h8ZgaqC0eYjGJ1uMdGPT/+b3eFncbG4NWuuP9QL+vWwRinu9waw7hkOLcpMJGVJAMgBwsPssMQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-runner@30.5.2: + resolution: {integrity: sha512-/B6px7hiiNhVSRwuv9AGn0nawYvwsHeQZ3ItTd5Gp2diFd0EOKaWVeWqcbw3L88vx1GfpCKjQkxWItZCTl11Rw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-runtime@30.5.2: + resolution: {integrity: sha512-0paUAHBlheai10A3XSy9Xh+YBG0IROy+/qzcDPzQ/nbbXrznQzeWy5qniICWK6d3W3scaRQCVAbXdcK0ibBq4w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-snapshot@30.5.2: + resolution: {integrity: sha512-jKIdes25AnAH73dOCi2qE6J6vHJ6L2vyBS11M89kT50DVJcLTf2AOjvcc+2vVaN8lUbY5v2R83aqXo3Ro9fqYA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-util@30.5.1: + resolution: {integrity: sha512-yKuxmNy2rSbTXw+3SIPanJo+nV4/BS1p26v44IYBFMsswSQySfMMcPHErnOncda7i9HEz0q605rIhSTBVgrZTg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-validate@30.5.1: + resolution: {integrity: sha512-i/buJ56wTpxihE93hQYNMfdOThS87+HGvLZzZJmU4xggPcdTYQq051iwALLCHp3q+SkCGH+EFejQZz5EbBSkkg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-watch-select-projects@2.0.0: + resolution: {integrity: sha512-j00nW4dXc2NiCW6znXgFLF9g8PJ0zP25cpQ1xRro/HU2GBfZQFZD0SoXnAlaoKkIY4MlfTMkKGbNXFpvCdjl1w==} + + jest-watch-typeahead@3.0.1: + resolution: {integrity: sha512-SFmHcvdueTswZlVhPCWfLXMazvwZlA2UZTrcE7MC3NwEVeWvEcOx6HUe+igMbnmA6qowuBSW4in8iC6J2EYsgQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + jest: ^30.0.0 + + jest-watcher@30.5.2: + resolution: {integrity: sha512-rqRgg4R11GA9m1UsEZwQeixHsgZReCn6TOHAHtIH33yXrIvoX0OGPA20Yzzjkz7X40fZvcRSxEpQppYPcWzmcQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-worker@30.5.1: + resolution: {integrity: sha512-Cbxh5v7AoLuFRmFJSM4/aHdQ68rjXvUWr716EE0Dh3I7T+T/3FgFKhOERGXHcU2Meftq9+9zxPM3TSNyI9D+HA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest@30.5.2: + resolution: {integrity: sha512-3gnpdBIza8ijCl3iMV9ChE3hSt1+46865qqod863gQtJr1DixOkAU5DoGbi3u+XlRcw++BhZQMu/y4xBdHBvSQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jimp-compact@0.16.1: + resolution: {integrity: sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.15.2: + resolution: {integrity: sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w==} + hasBin: true + + js-yaml@4.3.2: + resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} + hasBin: true + + jsc-safe-url@0.2.4: + resolution: {integrity: sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==} + + jsdom@26.1.0: + resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + lan-network@0.2.1: + resolution: {integrity: sha512-ONPnazC96VKDntab9j9JKwIWhZ4ZUceB4A9Epu4Ssg0hYFmtHZSeQ+n15nIwTFmcBUKtExOer8WTJ4GF9MO64A==} + hasBin: true + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.throttle@4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + + log-symbols@2.2.0: + resolution: {integrity: sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==} + engines: {node: '>=4'} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.5.3: + resolution: {integrity: sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + + memoize-one@5.2.1: + resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + metro-babel-transformer@0.87.1: + resolution: {integrity: sha512-orvRIGpb0yK1yMbk5YP3dhVKjmoxUkRB9fdltGJxNppEqus/1tFpNuf9KnGFR3Qjg0izoUrJ4z6WgoBvdkXPrA==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-babel-transformer@0.87.2: + resolution: {integrity: sha512-ZAfqGp0vttJFI6k1LEw//nGgTYfyVHFjcU61Ac7aPuTSaPsT/MeOi710ODfrxWkwK/y6z45NrIejjMwPv0CnxQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-cache-key@0.87.1: + resolution: {integrity: sha512-scqVVPMA2c+RVO12I3wyMDp5xCkRPLsyrcG4Qc3xfU5JR0EW/0sz2tjty+5UjMUtG09uiM1KYQ8HjWg7OQXHtw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-cache-key@0.87.2: + resolution: {integrity: sha512-wYtWOqRSaYlVtQe9B5YwobOFjf30IUuZZ6FqZ5cCTzisvh1varAdFCs/CGEWxBtJqe3qcgZKSi7cP4yoR0OZEQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-cache@0.87.1: + resolution: {integrity: sha512-juNPaj0Xi5tkLp8imXqvbSnEIijwKG36m7OiFFVJMqEkiURwAjkMFVek3/xpix1+LVQqO7kjVp3PvuvIM61mKQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-cache@0.87.2: + resolution: {integrity: sha512-2hWZsXhEYhhzYneNH8Q/ToZZKogcHDWhXTUloiJg+p+QGLEsDx9LXadxXXHfhPDaSRc9B6VOcB0Te02dPv/tRw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-config@0.87.1: + resolution: {integrity: sha512-NmkDlc/qZAdo5gTkVTuO2AKE/khemRKRH5IA+SKfqUBJigI5GqZ5TOXhmEokhlkAqzjt8dyzKhzI6FHvXoXaTQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-config@0.87.2: + resolution: {integrity: sha512-uIlI0RMKHUXI5xEe+7HkWgk8KFDjCCx7o/G/rcyqlUVbjM7N/3rDwCuT++dqC4UzeC4Afv1jDbS+bFI8/gRlNA==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-core@0.87.1: + resolution: {integrity: sha512-xizzky/4+c/Mkznege8OW05j7bSdM39VPoEps61Se4+hf32UQujmbvLvIE9+UnP6kNEPVomk0Fw8NsBK9iRQmw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-core@0.87.2: + resolution: {integrity: sha512-VlNETRpQXXSyj6hSU5l0xOANSAvJ81wIH/QpXcJ+nPbU6qteofQ0tsYO1HbtBIj/5MwbXjcEeDca9CJ2N40VZA==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-file-map@0.87.1: + resolution: {integrity: sha512-9sPuNCojC3pS4vj+ZPY7FXmHGpdJeckXuKXQrDAfJvZc60AF8owRFTkI8XdwlwrmPIB2w++KraK9FMEXvC4wJw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-file-map@0.87.2: + resolution: {integrity: sha512-zXB6o7Oj/xVGOhHQ+dz8BIAjZqjv1S1v/sJIqqRus8XiZISNspO3DmnKWssW0Gh2XO+Sq4TAjkIuYQnBJ+lnjA==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-minify-terser@0.87.1: + resolution: {integrity: sha512-YK4k1oO1wV48hfE+Nbw2rJCnAgeabzrgT/xH5ha5n9gbK4p3HYFC898cERUiyTl9vRh58CNTiXRc88f7y6PfKg==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-minify-terser@0.87.2: + resolution: {integrity: sha512-+sJo/F9+Xb+duOt4xA1HgNa9FRq1dsPcdTMxVrLsT1RVvgKVuA13qMeYvhR+vdlQbuXFXIrCCDOkMphxlM2/yA==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-resolver@0.87.1: + resolution: {integrity: sha512-FXH/brY69wT6sPxaSW8BhMmDGD/6irmBr/cL4rUi+VWwqR3pbvdcfUOfyjcHucgQ7pe5IW3xJY21eHKLVKNumQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-resolver@0.87.2: + resolution: {integrity: sha512-5irxge/5uJ+OqPwdj4GARrSmJVMVj4mkgn5WKv83X7NP9MH/AedDStqvZaMwEaiH/mQFm5W4GDbEqx1OJJeLBg==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-runtime@0.87.1: + resolution: {integrity: sha512-kjeuSvInsM6OzBjkCQsWxnkrKZFMKtnkCl38oXWRI9lDGs2L9hGs9Tak9sQYJ9h3gtDujneB7wZio+irgqJKDw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-runtime@0.87.2: + resolution: {integrity: sha512-68CLgcufiI162xyhSyI3Ax1kYPmUxKV6mt7Ll6gNd6Lb5ayJ+tQ1G7G+02Hda2ekV88Vq5zTsJ5hv2qpAhZa8g==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-source-map@0.87.1: + resolution: {integrity: sha512-Bqpm0PBGdy53pigIJb4HRF7QxD2pUOdgSmVh/4AWbP635kSCv+Y6ltVxUZgSnzS/QbSmzyCGijmRPlXMj2/qHw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-source-map@0.87.2: + resolution: {integrity: sha512-6jqJ/b+Ho36JmiI1pAjSWvnuDHqLCkF6Pjv4bxyjESu+18TrqvPwOS82QXQwyrr+haoc5kVnguxrgRWFhuqbEg==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-symbolicate@0.87.1: + resolution: {integrity: sha512-rcGvwabrg0lbXGRGRKl14PY3My3+dkno2jZYhdJEuH2DmjTtTkV5bYwgto4JtV/Lbe+sXE6GO1UGg654430uow==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + hasBin: true + + metro-symbolicate@0.87.2: + resolution: {integrity: sha512-bAE3KvaYjlyOzBHE+FI7NnG57bGoW+n9Et1leevreuMXYEaIhN/CmfCh3fRuApoj5LnJg1rFlxCXaJsIc4P5Gg==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + hasBin: true + + metro-transform-plugins@0.87.1: + resolution: {integrity: sha512-qMiJ/x+VfqumFJJSefKS6nj8uojzC29b2/aK8vlMuFABIqGjDucICEOXd2Yt6k/XMFAgAcaJvShUOT0HLyYaPw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-transform-plugins@0.87.2: + resolution: {integrity: sha512-pjss163wbj3G3bEANVJtzjIsHUeSP025aSlAxAla6QvwXFedD3tMDT19a9q2KRhp5OgfrDm/FbVusJuVHA0NYg==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-transform-worker@0.87.1: + resolution: {integrity: sha512-VOzs3OV405FuOLYdAhqA2wsn1F9lvueDVxMDLvCKaQ44U+yknIqphJ9eMjjsGwLDZiJq9sW3DMLhjD27JxQgqQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-transform-worker@0.87.2: + resolution: {integrity: sha512-DLpo4Xl2vShovtqXfB1JYJPAWsWjzuLlbmWYscOr0qpshjZ8Ii6JBDEnFBOVEzeXNyRG/gr697v61N25N9YvDg==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro@0.87.1: + resolution: {integrity: sha512-1oyLU9elM7hPAsKIqKooEekwxiuWr27+MZBhUROPhzcbXhMDxK64GPF/hCXwBZVp1F89ODavCrBmJtLx9WtBoQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + hasBin: true + + metro@0.87.2: + resolution: {integrity: sha512-SPdGRafxrx7pf2bNta9qvwfX6tFMxULEEDM5irfsPH+AinubUoLqZUkguJl6bwCZOVO4hOGgjr7esiSDqPjkoQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + hasBin: true + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mimic-fn@1.2.0: + resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==} + engines: {node: '>=4'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + multitars@1.0.2: + resolution: {integrity: sha512-6GwVw5eLi9sThdtlS4PKwC7yRLaf45pYhIEzKBHdKxi+YOXGKFX8acIniH+Uh/+k9mS2lQOupTccjoe5r0/1IQ==} + + nanoid@3.3.20: + resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + napi-postinstall@0.3.7: + resolution: {integrity: sha512-jyU4cU4kVAmy/3qjP+DcoQTNXfINHc+dFw54gGqWC8nu0mpV0kOnk7kff+J+Q18SbX0k3Np8Rm7yFjd3phatNQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + negotiator@1.1.0: + resolution: {integrity: sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==} + engines: {node: '>=18'} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-forge@1.4.2: + resolution: {integrity: sha512-rRtAR5XLJ8gCKd9du4qrKAsgCG1ObGP4gLeNJMa4vYSeq4bmBMOJk5IHkrviBV0q7uoAJlVd8HEQYQSVUb4FGQ==} + engines: {node: '>= 6.13.0'} + + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-releases@2.0.60: + resolution: {integrity: sha512-OmO8+GM1JUZqXET720VrJCwkjUCXmCMQm0Z3UDDRbfNLHS4NEAvY60j5jiFv0tkKw2PNNlqOLhahVmwJIOLDIQ==} + engines: {node: '>=18'} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + noxcturnal@0.1.11: + resolution: {integrity: sha512-nKgZ4mQpWz5Nry5KRqRcyCv37Uc24VH9UkNsIJJ58sC7ubyXtaiP4zfjOAsGiTVZIJ6rcfkmbYS0P4plVhdHEQ==} + engines: {node: '>=18'} + + npm-package-arg@11.0.3: + resolution: {integrity: sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==} + engines: {node: ^16.14.0 || >=18.0.0} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + nullthrows@1.1.1: + resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} + + nwsapi@2.2.28: + resolution: {integrity: sha512-IlVB7OS7qrOsVYlpnFIkETjMwT9jwvmocJmmM+GZU/PAB3uGi9Ezd7vcWhWBUnSc0ya4ppmQITOyP1ez9gg8cg==} + + ob1@0.87.1: + resolution: {integrity: sha512-i8iA8uij0g1YQzS8uOJPSRCgwDjO9warIHUAu1Fqj877Wc3wlfxDYBioYWgKTBF2+URVJttyDWSEpmd99nlvtQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + ob1@0.87.2: + resolution: {integrity: sha512-KLdsz/5QTEG2Y7lhxEOYNBZX7MkD0m3Cu11B72TBJ6sCKGXYatLJ/4WtMKoGLalQyozFYDutPRpsWpDRRA+E4g==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + + on-finished@2.4.2: + resolution: {integrity: sha512-ATWUv387i+nLD49EiDoOft5scf32Vsdz3ktrQJG9bi7jRFmaXTssvyvj1EmeKVVgvesbqUtvQQvaS2TpTukAZQ==} + engines: {node: '>= 0.8'} + + on-headers@1.1.0: + resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@2.0.1: + resolution: {integrity: sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==} + engines: {node: '>=4'} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + ora@3.4.0: + resolution: {integrity: sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==} + engines: {node: '>=6'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse-png@2.1.0: + resolution: {integrity: sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==} + engines: {node: '>=10'} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} + engines: {node: '>=12'} + + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + plist@3.1.1: + resolution: {integrity: sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==} + engines: {node: '>=10.4.0'} + + pngjs@3.4.0: + resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==} + engines: {node: '>=4.0.0'} + + postcss@8.5.32: + resolution: {integrity: sha512-LJlKCCAUFKOuZxipUdYw1NzIITEsPcgyOG9LkvRJvuKj/bRzbuRY0ARXvL0pWGpsZvn8jku+LMep2eU0seHp8g==} + engines: {node: ^10 || ^12 || >=14} + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + pretty-format@30.5.1: + resolution: {integrity: sha512-byhRAPguVKMQIj4kjJwJ5lAskVhfuiSdiYl/aLTWpgkGEmic2jYhJh1yE9ih8Ox44Xg9ccCT11/S6QrzSJuNrg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + proc-log@4.2.0: + resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + promise@8.3.0: + resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pure-rand@7.0.1: + resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + react-devtools-core@6.1.5: + resolution: {integrity: sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==} + + react-dom@19.3.1: + resolution: {integrity: sha512-Y0bARz53lhEC1NMCASs0/j+faB/zqt3R8hpvg1e8+61ZVJ4UL0UdC4cBbXfZMcIuhrfgeILTLe+ZeBCavQPtKQ==} + peerDependencies: + react: ^19.3.1 + + react-fast-compare@3.2.2: + resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} + + react-freeze@1.0.4: + resolution: {integrity: sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA==} + engines: {node: '>=10'} + peerDependencies: + react: '>=17.0.0' + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + react-is@19.3.1: + resolution: {integrity: sha512-RRieF6IyxQBkcK6pP8xOHprLTPW6QjRkbGdImtqNme+/hYVwCZkLQLdlZGOhUqXwkS9IEynaGvPJtv6XB/cz0Q==} + + react-native-drawer-layout@4.2.12: + resolution: {integrity: sha512-qYmntEctkMSodN7pnC2llV21nswImLFPHJeT3PJXSJqZdU4jzDATR8iVi66sXkrtoOLJ2+EvXxgd7sMMpV4ViA==} + peerDependencies: + react: '>= 18.2.0' + react-native: '*' + react-native-gesture-handler: '>= 2.0.0' + react-native-reanimated: '>= 2.0.0' + + react-native-gesture-handler@3.4.0: + resolution: {integrity: sha512-jBg4ZWDvegeaZ4OHq9oxVOS/Qa6pV+LhtsUExothyhWxqzG0Lkg7kl2ztemPj/pnJxkq9j/+6wAw3jZGwdssww==} + peerDependencies: + react: '*' + react-native: '*' + + react-native-is-edge-to-edge@1.3.1: + resolution: {integrity: sha512-NIXU/iT5+ORyCc7p0z2nnlkouYKX425vuU1OEm6bMMtWWR9yvb+Xg5AZmImTKoF9abxCPqrKC3rOZsKzUYgYZA==} + peerDependencies: + react: '*' + react-native: '*' + + react-native-reanimated@4.7.1: + resolution: {integrity: sha512-HviDFSZ6V4KTRsrLS6hRbBJ4j63l/L8a5az0EoWdJwaMLYnBNyYISTDxwXpEYkMbAbLzCMCviIdiOxXHYQWcNA==} + peerDependencies: + react: '*' + react-native: 0.86 - 0.88 + react-native-worklets: 0.13.x + + react-native-safe-area-context@5.10.1: + resolution: {integrity: sha512-ax0T3cAHQIhuAjDQpJ9C1Le96aRiM9PF+Kmgg7Y8+mD7QJMEIx04cG0eG3EGUTdvymgOkCrkakgZFwuOIuNQGw==} + peerDependencies: + react: '*' + react-native: '*' + + react-native-screens@4.30.1: + resolution: {integrity: sha512-wLzZSQpvMx3FxIlDnb6raDJjsv2x45tFLGFz8RFUvxHzsKU9dWOkZYv9fy2siWtFf3eWGcRh66hL+o+dHhRJLQ==} + peerDependencies: + react: '*' + react-native: '*' + + react-native-worklets@0.13.1: + resolution: {integrity: sha512-sX55Vx89/Y9uJmvAbAGoHXBZvCWXtYPGWPJ9Z9yl0h76mP9A10ULlSrixzGqBFLXeQMBpIpyJEhWpzXP7GG6YA==} + peerDependencies: + '@babel/core': '*' + '@react-native/metro-config': '*' + react: '*' + react-native: 0.86 - 0.88 + + react-native@0.88.1: + resolution: {integrity: sha512-wajWcLZ93GCN7k4Uwh4CS4L2Ah8ohcvkOXnvIYmh4Yvuqho5j3APZ9qozK+nQrHWSgauq4h8D3HN5DKK84SrHA==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + hasBin: true + peerDependencies: + '@types/react': ^19.1.1 + react: ^19.3.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-reconciler@0.34.0: + resolution: {integrity: sha512-eVibvB1fc9j5Qf1KRkiM3GzRPBdjg2P6G6QV2f3P6Eb3OGMxRBhdg2rrUwjbV5JrQaJj8nOa8uajmmJA5tJWjQ==} + engines: {node: '>=0.10.0'} + peerDependencies: + react: ^19.3.0 + + react-refresh@0.14.2: + resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} + engines: {node: '>=0.10.0'} + + react@19.3.0: + resolution: {integrity: sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==} + engines: {node: '>=0.10.0'} + + regenerate-unicode-properties@10.3.0: + resolution: {integrity: sha512-9ns8odR8e9q3otKeHj3DE80jZYKg6zVeZKE+zQmRKXFoVUcuiTGeO6iusDhPRoIQQPVPRvH+SfBhrTud4eczuw==} + engines: {node: '>=4'} + + regenerate@1.5.0: + resolution: {integrity: sha512-1s+CxXjJ71i7LNVy8nYwg47XV4y6lAnOEhsMtSKq3WpmPfhl9LuKlTqKIn/3yUpE8lBz+W+TT88Bxyhnr0U4yw==} + + regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + + regexpu-core@6.5.3: + resolution: {integrity: sha512-E8VgUoSK+LMQrLboDxavm76MTBGrQhx9RiNuomRmYnZ10Uw12HrI8fkxOOncktb2hBpzIZ9SV/347euQHG5z+g==} + engines: {node: '>=4'} + + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.13.4: + resolution: {integrity: sha512-EWV80YgFaVgFrjGCAsV7oybp4GOxbls5RzBg8OB0nKEVXsBJR1JlV8Di1JhCROg3MzTfe1RI8yitIm1eOs68iA==} + hasBin: true + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-workspace-root@2.0.1: + resolution: {integrity: sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w==} + + resolve@1.22.13: + resolution: {integrity: sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==} + engines: {node: '>= 0.4'} + hasBin: true + + restore-cursor@2.0.0: + resolution: {integrity: sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==} + engines: {node: '>=4'} + + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sandbox-cli-detector@0.2.0: + resolution: {integrity: sha512-4lyHX0ZU0AZKwjgZ1InxZAa3PNpyEb8rOQ+Zss1ReYmhNzW0Q+h1zE5nvniXN0HaAWZaZE1zgVNEirb0R7LmNg==} + engines: {node: '>=18.18'} + hasBin: true + + sax@1.6.1: + resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==} + engines: {node: '>=11.0.0'} + + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + + scheduler@0.28.0: + resolution: {integrity: sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.2: + resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} + engines: {node: '>= 0.8.0'} + + serialize-error@2.1.0: + resolution: {integrity: sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==} + engines: {node: '>=0.10.0'} + + serve-static@1.16.3: + resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} + engines: {node: '>= 0.8.0'} + + server-only@0.0.1: + resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + sf-symbols-typescript@2.2.0: + resolution: {integrity: sha512-TPbeg0b7ylrswdGCji8FRGFAKuqbpQlLbL8SOle3j1iHSs5Ob5mhvMAxWN2UItOjgALAB5Zp3fmMfj8mbWvXKw==} + engines: {node: '>=10'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shell-quote@1.12.0: + resolution: {integrity: sha512-PcByqNyT/38F2kDNi006HAMRJaULuBzq/FOsw3qdZvX/GA9W/jamDaRskgHjubHiftXK5sIFxLNkvrXUwcof6Q==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-plist@1.3.1: + resolution: {integrity: sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==} + + simple-swizzle@0.2.4: + resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + + slugify@1.6.9: + resolution: {integrity: sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==} + engines: {node: '>=8.0.0'} + + source-map-js@1.2.2: + resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.5.6: + resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} + engines: {node: '>=0.10.0'} + + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stack-generator@2.0.10: + resolution: {integrity: sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==} + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + stackframe@1.3.4: + resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + + stacktrace-gps@3.1.2: + resolution: {integrity: sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==} + + stacktrace-js@2.0.2: + resolution: {integrity: sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==} + + stacktrace-parser@0.1.11: + resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==} + engines: {node: '>=6'} + + standard-navigation@0.0.5: + resolution: {integrity: sha512-YAmzwAiiQVocZxO/VGPFiQHcu5pKiz09QIGC0MK6aRMoa3E0QkoTQgcqJr7ZZ3OMiNhu4DkaGElFI5htjOIDbw==} + + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + stream-buffers@2.2.0: + resolution: {integrity: sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==} + engines: {node: '>= 0.10.0'} + + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + + string-length@6.0.0: + resolution: {integrity: sha512-1U361pxZHEQ+FeSjzqRpV+cu2vTzYeWeafXFLykiFlv4Vc0n3njgU8HrMbyik5uwm77naWMuVG8fhEF+Ovb1Kg==} + engines: {node: '>=16'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + strip-ansi@5.2.0: + resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} + engines: {node: '>=6'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + structured-headers@0.4.1: + resolution: {integrity: sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-hyperlinks@2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + synckit@0.11.13: + resolution: {integrity: sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==} + engines: {node: ^14.18.0 || >=16.0.0} + + tagged-tag@1.0.0: + resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} + engines: {node: '>=20'} + + terminal-link@2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + + terser@5.51.2: + resolution: {integrity: sha512-bWnjSNscmuI+GJze6ZupnHP8G/cTcsJF+bXCeQknk2SHQsgbNJnLrqiH9jZ2W4STPVXH2mDKKRX3iwPhc9Cn/Q==} + engines: {node: '>=10'} + hasBin: true + + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + + test-exclude@7.0.2: + resolution: {integrity: sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==} + engines: {node: '>=18'} + + test-renderer@1.3.0: + resolution: {integrity: sha512-DXyHv7JrVmDc5dKpfVHFhJ0Evo/EFY3TqlNt8CR65ua3SCsI09K/mQDJmYUOnZz36GANYqjp0ApeRER/mOxktQ==} + peerDependencies: + react: ^19.0.0 + + throat@5.0.0: + resolution: {integrity: sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tldts-core@6.1.86: + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + + tldts@6.1.86: + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} + hasBin: true + + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + toqr@0.1.1: + resolution: {integrity: sha512-FWAPzCIHZHnrE/5/w9MPk0kK25hSQSH2IKhYh9PyjS3SG/+IEMvlwIHbhz+oF7xl54I+ueZlVnMjyzdSwLmAwA==} + + tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + engines: {node: '>=16'} + + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@0.7.1: + resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} + engines: {node: '>=8'} + + type-fest@5.10.0: + resolution: {integrity: sha512-NoSdpq/WEiAg5sjmBkmV/hfxv6HJH4NqPNrqjtSO5CwRmpsDfaf4begxW34KdJykH/l1yHtwBWQkCRdoXO8mPA==} + engines: {node: '>=20'} + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + ua-parser-js@0.7.41: + resolution: {integrity: sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==} + hasBin: true + + undici-types@8.9.0: + resolution: {integrity: sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + + unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + + unicode-match-property-value-ecmascript@2.2.1: + resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} + engines: {node: '>=4'} + + unicode-property-aliases-ecmascript@2.2.0: + resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} + engines: {node: '>=4'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + unrs-resolver@1.12.2: + resolution: {integrity: sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==} + + update-browserslist-db@1.3.4: + resolution: {integrity: sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + use-latest-callback@0.2.6: + resolution: {integrity: sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg==} + peerDependencies: + react: '>=16.8' + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + + validate-npm-package-name@5.0.1: + resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vlq@1.0.1: + resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==} + + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + + warn-once@0.1.1: + resolution: {integrity: sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==} + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-fetch@3.6.20: + resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url-minimum@0.2.0: + resolution: {integrity: sha512-BtjXU1caNcCFfETP2DhqSeVPfRDl2MTUitI107RE34rJXjR/izfUtR5IoTFOK1WqjNLXbbeqaCH/mQAOLjpc8g==} + + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ws@7.5.13: + resolution: {integrity: sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.22.0: + resolution: {integrity: sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xcode@4.0.0: + resolution: {integrity: sha512-dDaoWzc9EP2fp9FS9PVZUkyvFxY4y1TOV9pcKaKLk++Ei/qb97XDFEVP7GnW7Osii/TzVABJ0jq2F+9/lq0TVA==} + engines: {node: '>=14.17.0'} + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xml2js@0.6.0: + resolution: {integrity: sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==} + engines: {node: '>=4.0.0'} + + xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + + xmlbuilder@15.1.1: + resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} + engines: {node: '>=8.0'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.3: + resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + + zustand@5.0.16: + resolution: {integrity: sha512-Uv7e327ihlCfayfja3hDc0M64Upev1LWBKpRobdK4NyovDDPeeX4imWXc/wzC1yc6fkYPoAY/ncKVPAs2jrtQw==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + + zxing-wasm@3.1.6: + resolution: {integrity: sha512-mU7UNuvl+hOT+nlSOQTMHZ2tM8lRMsbjDIp5IO/+HmBl/FOq77q0OSZPJ3cm42A9c1MKU6Uve67FiGdkhsrT9g==} + peerDependencies: + '@types/emscripten': '>=1.39.6' + +snapshots: + + 2g@1.0.1(typescript@6.0.3): + optionalDependencies: + typescript: 6.0.3 + + '@asamuzakjp/css-color@3.2.0': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 10.4.3 + + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.29.7(supports-color@8.1.1)': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helpers': 7.29.10 + '@babel/parser': 7.29.11 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.10(supports-color@8.1.1) + '@babel/types': 7.29.11 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3(supports-color@8.1.1) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.8': + dependencies: + '@babel/parser': 7.29.11 + '@babel/types': 7.29.11 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.29.7': + dependencies: + '@babel/types': 7.29.11 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.29.5 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-member-expression-to-functions': 7.29.7(supports-color@8.1.1) + '@babel/helper-optimise-call-expression': 7.29.7 + '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) + '@babel/traverse': 7.29.10(supports-color@8.1.1) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.29.10(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.29.7 + regexpu-core: 6.5.3 + semver: 6.3.1 + + '@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + debug: 4.4.3(supports-color@8.1.1) + lodash.debounce: 4.0.8 + resolve: 1.22.13 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-member-expression-to-functions@7.29.7(supports-color@8.1.1)': + dependencies: + '@babel/traverse': 7.29.10(supports-color@8.1.1) + '@babel/types': 7.29.11 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.29.7(supports-color@8.1.1)': + dependencies: + '@babel/traverse': 7.29.10(supports-color@8.1.1) + '@babel/types': 7.29.11 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.10(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.29.7': + dependencies: + '@babel/types': 7.29.11 + + '@babel/helper-plugin-utils@7.29.7': {} + + '@babel/helper-remap-async-to-generator@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-wrap-function': 7.29.7(supports-color@8.1.1) + '@babel/traverse': 7.29.10(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-member-expression-to-functions': 7.29.7(supports-color@8.1.1) + '@babel/helper-optimise-call-expression': 7.29.7 + '@babel/traverse': 7.29.10(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.29.7(supports-color@8.1.1)': + dependencies: + '@babel/traverse': 7.29.10(supports-color@8.1.1) + '@babel/types': 7.29.11 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.29.11': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helper-wrap-function@7.29.7(supports-color@8.1.1)': + dependencies: + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.10(supports-color@8.1.1) + '@babel/types': 7.29.11 + transitivePeerDependencies: + - supports-color + + '@babel/helpers@7.29.10': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.11 + + '@babel/parser@7.29.11': + dependencies: + '@babel/types': 7.29.11 + + '@babel/plugin-proposal-decorators@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-decorators': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-export-default-from@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-decorators@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-export-default-from@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-flow@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-import-attributes@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-arrow-functions@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-async-generator-functions@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/traverse': 7.29.10(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-block-scoping@7.29.11(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-class-properties@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-static-block@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.29.11(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/traverse': 7.29.10(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-destructuring@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/traverse': 7.29.10(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-export-namespace-from@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-flow-strip-types@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-flow': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + + '@babel/plugin-transform-for-of@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-logical-assignment-operators@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-create-regexp-features-plugin': 7.29.10(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-nullish-coalescing-operator@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-object-rest-spread@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/traverse': 7.29.10(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-catch-binding@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-optional-chaining@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-private-methods@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-private-property-in-object@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-display-name@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-react-jsx-development@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-react-jsx@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/types': 7.29.11 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-pure-annotations@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-regenerator@7.29.8(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-shorthand-properties@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-template-literals@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-typescript@7.29.9(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@8.1.1) + '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-unicode-regex@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-create-regexp-features-plugin': 7.29.10(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/preset-typescript@7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-typescript': 7.29.9(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/runtime@7.29.10': {} + + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.11 + '@babel/types': 7.29.11 + + '@babel/traverse@7.29.10(supports-color@8.1.1)': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.11 + '@babel/template': 7.29.7 + '@babel/types': 7.29.11 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.11': + dependencies: + '@babel/helper-string-parser': 7.29.11 + '@babel/helper-validator-identifier': 7.29.7 + + '@bcoe/v8-coverage@0.2.3': {} + + '@csstools/color-helpers@5.1.0': {} + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-tokenizer@3.0.4': {} + + '@emnapi/core@1.10.0': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@expo/cli@58.1.17(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.15)(expo-constants@58.0.14)(expo-font@58.0.11(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0))(expo-router@58.0.28)(expo@58.0.21)(react-dom@19.3.1(react@19.3.0))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3)': + dependencies: + 2g: 1.0.1(typescript@6.0.3) + '@expo/code-signing-certificates': 0.0.7 + '@expo/config': 58.0.9(supports-color@8.1.1)(typescript@6.0.3) + '@expo/config-plugins': 58.0.11(supports-color@8.1.1)(typescript@6.0.3) + '@expo/devcert': 1.2.2(supports-color@8.1.1) + '@expo/env': 2.5.3(supports-color@8.1.1) + '@expo/image-utils': 0.12.6(supports-color@8.1.1)(typescript@6.0.3) + '@expo/inline-modules': 0.2.8(supports-color@8.1.1)(typescript@6.0.3) + '@expo/json-file': 11.2.1 + '@expo/log-box': 58.0.13(@expo/dom-webview@58.0.2)(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + '@expo/log-box-utils': 58.0.2 + '@expo/metro': 58.0.0(supports-color@8.1.1) + '@expo/metro-config': 58.0.19(expo@58.0.21)(supports-color@8.1.1)(typescript@6.0.3) + '@expo/metro-file-map': 58.0.5(supports-color@8.1.1)(typescript@6.0.3) + '@expo/osascript': 2.8.1 + '@expo/package-manager': 1.14.2 + '@expo/platforms': 58.0.1 + '@expo/plist': 0.10.1 + '@expo/prebuild-config': 58.0.17(supports-color@8.1.1)(typescript@6.0.3) + '@expo/require-utils': 58.0.5(supports-color@8.1.1)(typescript@6.0.3) + '@expo/router-server': 58.0.19(@expo/metro-runtime@58.0.15)(expo-constants@58.0.14)(expo-font@58.0.11(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0))(expo-router@58.0.28)(expo-server@58.0.6)(expo@58.0.21)(react-dom@19.3.1(react@19.3.0))(react@19.3.0)(supports-color@8.1.1) + '@expo/schema-utils': 58.0.2 + '@expo/spawn-async': 1.8.0 + '@expo/ws-tunnel': 2.0.1(ws@8.22.0) + '@expo/xcpretty': 4.4.7 + '@react-native/asset-utils': 0.88.1 + '@react-native/dev-middleware': 0.88.1(supports-color@8.1.1) + '@react-native/js-polyfills': 0.88.1 + accepts: 1.3.8 + agent-cli-detector: 0.1.7 + arg: 5.0.2 + bplist-creator: 0.1.0 + bplist-parser: 0.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + compression: 1.8.2(supports-color@8.1.1) + connect: 3.7.0(supports-color@8.1.1) + dnssd-advertise: 1.1.6 + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + expo-server: 58.0.6 + fetch-nodeshim: 0.4.10 + getenv: 2.0.0 + glob: 13.0.6 + lan-network: 0.2.1 + multitars: 1.0.2 + node-forge: 1.4.2 + npm-package-arg: 11.0.3 + ora: 3.4.0 + picomatch: 4.0.7 + pretty-format: 29.7.0 + progress: 2.0.3 + prompts: 2.4.2 + resolve-from: 5.0.0 + sandbox-cli-detector: 0.2.0 + semver: 7.8.5 + send: 0.19.2(supports-color@8.1.1) + slugify: 1.6.9 + stacktrace-parser: 0.1.11 + structured-headers: 0.4.1 + terminal-link: 2.1.1 + toqr: 0.1.1 + wrap-ansi: 7.0.0 + ws: 8.22.0 + zod: 3.25.76 + optionalDependencies: + expo-router: 58.0.28(01c662b7665e4b62efc6a8f6b7abec47) + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + transitivePeerDependencies: + - '@expo/dom-webview' + - '@expo/metro-runtime' + - bufferutil + - expo-constants + - expo-font + - react + - react-dom + - react-server-dom-webpack + - supports-color + - typescript + - utf-8-validate + + '@expo/code-signing-certificates@0.0.7': + dependencies: + node-forge: 1.4.2 + + '@expo/config-plugins@58.0.11(supports-color@8.1.1)(typescript@6.0.3)': + dependencies: + '@expo/config-types': 58.0.3 + '@expo/json-file': 11.2.1 + '@expo/plist': 0.10.1 + '@expo/require-utils': 58.0.5(supports-color@8.1.1)(typescript@6.0.3) + '@expo/sdk-runtime-versions': 1.0.1 + chalk: 4.1.2 + debug: 4.4.3(supports-color@8.1.1) + getenv: 2.0.0 + glob: 13.0.6 + semver: 7.8.5 + slugify: 1.6.9 + xcode: 4.0.0 + xml2js: 0.6.0 + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/config-types@58.0.3': {} + + '@expo/config@58.0.9(supports-color@8.1.1)(typescript@6.0.3)': + dependencies: + '@expo/config-plugins': 58.0.11(supports-color@8.1.1)(typescript@6.0.3) + '@expo/config-types': 58.0.3 + '@expo/json-file': 11.2.1 + '@expo/platforms': 58.0.1 + '@expo/require-utils': 58.0.5(supports-color@8.1.1)(typescript@6.0.3) + deepmerge: 4.3.1 + getenv: 2.0.0 + glob: 13.0.6 + resolve-workspace-root: 2.0.1 + semver: 7.8.5 + slugify: 1.6.9 + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/devcert@1.2.2(supports-color@8.1.1)': + dependencies: + '@expo/sudo-prompt': 9.3.2 + debug: 3.2.7(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@expo/devtools@58.0.2(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)': + dependencies: + chalk: 4.1.2 + optionalDependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + + '@expo/dom-webview@58.0.2(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)': + dependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + + '@expo/env@2.5.3(supports-color@8.1.1)': + dependencies: + chalk: 4.1.2 + debug: 4.4.3(supports-color@8.1.1) + getenv: 2.0.0 + transitivePeerDependencies: + - supports-color + + '@expo/fingerprint@0.21.7(supports-color@8.1.1)': + dependencies: + '@expo/env': 2.5.3(supports-color@8.1.1) + '@expo/spawn-async': 1.8.0 + arg: 5.0.2 + chalk: 4.1.2 + debug: 4.4.3(supports-color@8.1.1) + getenv: 2.0.0 + glob: 13.0.6 + ignore: 5.3.2 + minimatch: 10.2.6 + resolve-from: 5.0.0 + semver: 7.8.5 + transitivePeerDependencies: + - supports-color + + '@expo/image-utils@0.12.6(supports-color@8.1.1)(typescript@6.0.3)': + dependencies: + '@expo/require-utils': 58.0.5(supports-color@8.1.1)(typescript@6.0.3) + '@expo/spawn-async': 1.8.0 + chalk: 4.1.2 + getenv: 2.0.0 + jimp-compact: 0.16.1 + parse-png: 2.1.0 + semver: 7.8.5 + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/inline-modules@0.2.8(supports-color@8.1.1)(typescript@6.0.3)': + dependencies: + '@expo/config-plugins': 58.0.11(supports-color@8.1.1)(typescript@6.0.3) + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/json-file@11.2.1': + dependencies: + '@babel/code-frame': 7.29.7 + json5: 2.2.3 + + '@expo/local-build-cache-provider@58.0.9(supports-color@8.1.1)(typescript@6.0.3)': + dependencies: + '@expo/config': 58.0.9(supports-color@8.1.1)(typescript@6.0.3) + chalk: 4.1.2 + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/log-box-utils@58.0.2': {} + + '@expo/log-box@58.0.13(@expo/dom-webview@58.0.2)(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)': + dependencies: + '@expo/dom-webview': 58.0.2(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + '@expo/log-box-utils': 58.0.2 + anser: 1.4.10 + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + stacktrace-parser: 0.1.11 + optionalDependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + + '@expo/metro-config@58.0.19(expo@58.0.21)(supports-color@8.1.1)(typescript@6.0.3)': + dependencies: + 2g: 1.0.1(typescript@6.0.3) + '@babel/code-frame': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/generator': 7.29.8 + '@expo/config': 58.0.9(supports-color@8.1.1)(typescript@6.0.3) + '@expo/env': 2.5.3(supports-color@8.1.1) + '@expo/json-file': 11.2.1 + '@expo/metro': 58.0.0(supports-color@8.1.1) + '@expo/platforms': 58.0.1 + '@expo/require-utils': 58.0.5(supports-color@8.1.1)(typescript@6.0.3) + '@expo/spawn-async': 1.8.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/remapping': 2.3.5 + '@jridgewell/sourcemap-codec': 1.6.0 + '@jridgewell/trace-mapping': 0.3.31 + '@react-native/js-polyfills': 0.88.1 + browserslist: 4.29.5 + chalk: 4.1.2 + debug: 4.4.3(supports-color@8.1.1) + getenv: 2.0.0 + glob: 13.0.6 + hermes-parser: 0.36.1 + jsc-safe-url: 0.2.4 + lightningcss: 1.33.0 + noxcturnal: 0.1.11 + picomatch: 4.0.7 + postcss: 8.5.32 + resolve-from: 5.0.0 + optionalDependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + transitivePeerDependencies: + - bufferutil + - supports-color + - typescript + - utf-8-validate + + '@expo/metro-file-map@58.0.5(supports-color@8.1.1)(typescript@6.0.3)': + dependencies: + 2g: 1.0.1(typescript@6.0.3) + debug: 4.4.3(supports-color@8.1.1) + fb-watchman: 2.0.4 + invariant: 2.2.4 + jest-worker: 29.7.0 + walker: 1.0.8 + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/metro-runtime@58.0.15(@expo/log-box@58.0.13)(expo@58.0.21)(react-dom@19.3.1(react@19.3.0))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)': + dependencies: + '@expo/log-box': 58.0.13(@expo/dom-webview@58.0.2)(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + anser: 1.4.10 + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + pretty-format: 29.7.0 + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + stacktrace-parser: 0.1.11 + whatwg-fetch: 3.6.20 + optionalDependencies: + react-dom: 19.3.1(react@19.3.0) + + '@expo/metro@58.0.0(supports-color@8.1.1)': + dependencies: + metro: 0.87.1(supports-color@8.1.1) + metro-babel-transformer: 0.87.1(supports-color@8.1.1) + metro-cache: 0.87.1(supports-color@8.1.1) + metro-cache-key: 0.87.1 + metro-config: 0.87.1(supports-color@8.1.1) + metro-core: 0.87.1 + metro-file-map: 0.87.1(supports-color@8.1.1) + metro-minify-terser: 0.87.1 + metro-resolver: 0.87.1 + metro-runtime: 0.87.1 + metro-source-map: 0.87.1(supports-color@8.1.1) + metro-symbolicate: 0.87.1 + metro-transform-plugins: 0.87.1(supports-color@8.1.1) + metro-transform-worker: 0.87.1(supports-color@8.1.1) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@expo/modules-macros-linux-arm64@0.27.1': + optional: true + + '@expo/modules-macros-linux-x64@0.27.1': + optional: true + + '@expo/modules-macros-win32-arm64@0.27.1': + optional: true + + '@expo/modules-macros-win32-x64@0.27.1': + optional: true + + '@expo/osascript@2.8.1': + dependencies: + '@expo/spawn-async': 1.8.0 + + '@expo/package-manager@1.14.2': + dependencies: + '@expo/json-file': 11.2.1 + '@expo/spawn-async': 1.8.0 + chalk: 4.1.2 + npm-package-arg: 11.0.3 + ora: 3.4.0 + resolve-workspace-root: 2.0.1 + + '@expo/platforms@58.0.1': {} + + '@expo/plist@0.10.1': + dependencies: + '@xmldom/xmldom': 0.8.15 + base64-js: 1.5.1 + xmlbuilder: 15.1.1 + + '@expo/prebuild-config@58.0.17(supports-color@8.1.1)(typescript@6.0.3)': + dependencies: + '@expo/config': 58.0.9(supports-color@8.1.1)(typescript@6.0.3) + '@expo/config-plugins': 58.0.11(supports-color@8.1.1)(typescript@6.0.3) + '@expo/config-types': 58.0.3 + '@expo/image-utils': 0.12.6(supports-color@8.1.1)(typescript@6.0.3) + '@expo/json-file': 11.2.1 + '@react-native/normalize-colors': 0.88.1 + debug: 4.4.3(supports-color@8.1.1) + expo-modules-autolinking: 58.0.16(supports-color@8.1.1)(typescript@6.0.3) + resolve-from: 5.0.0 + semver: 7.8.5 + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/require-utils@58.0.5(supports-color@8.1.1)(typescript@6.0.3)': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@expo/router-server@58.0.19(@expo/metro-runtime@58.0.15)(expo-constants@58.0.14)(expo-font@58.0.11(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0))(expo-router@58.0.28)(expo-server@58.0.6)(expo@58.0.21)(react-dom@19.3.1(react@19.3.0))(react@19.3.0)(supports-color@8.1.1)': + dependencies: + debug: 4.4.3(supports-color@8.1.1) + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + expo-constants: 58.0.14(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + expo-font: 58.0.11(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + expo-server: 58.0.6 + react: 19.3.0 + optionalDependencies: + '@expo/metro-runtime': 58.0.15(@expo/log-box@58.0.13)(expo@58.0.21)(react-dom@19.3.1(react@19.3.0))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + expo-router: 58.0.28(01c662b7665e4b62efc6a8f6b7abec47) + react-dom: 19.3.1(react@19.3.0) + transitivePeerDependencies: + - supports-color + + '@expo/schema-utils@58.0.2': {} + + '@expo/sdk-runtime-versions@1.0.1': {} + + '@expo/spawn-async@1.8.0': + dependencies: + cross-spawn: 7.0.6 + + '@expo/sudo-prompt@9.3.2': {} + + '@expo/ws-tunnel@2.0.1(ws@8.22.0)': + dependencies: + ws: 8.22.0 + + '@expo/xcpretty@4.4.7': + dependencies: + '@babel/code-frame': 7.29.7 + chalk: 4.1.2 + js-yaml: 4.3.2 + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@isaacs/ttlcache@1.4.1': {} + + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.15.2 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.6': {} + + '@jest/console@30.5.2': + dependencies: + '@jest/types': 30.5.1 + '@types/node': 26.6.6 + chalk: 4.1.2 + jest-message-util: 30.5.1 + jest-util: 30.5.1 + slash: 3.0.0 + + '@jest/core@30.5.2(supports-color@8.1.1)': + dependencies: + '@jest/console': 30.5.2 + '@jest/pattern': 30.5.0 + '@jest/reporters': 30.5.2(supports-color@8.1.1) + '@jest/test-result': 30.5.2 + '@jest/transform': 30.5.2(supports-color@8.1.1) + '@jest/types': 30.5.1 + '@types/node': 26.6.6 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 4.4.0 + exit-x: 0.2.2 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-changed-files: 30.5.1 + jest-config: 30.5.2(@types/node@26.6.6)(supports-color@8.1.1) + jest-haste-map: 30.5.1 + jest-message-util: 30.5.1 + jest-regex-util: 30.5.0 + jest-resolve: 30.5.1 + jest-resolve-dependencies: 30.5.2(supports-color@8.1.1) + jest-runner: 30.5.2(supports-color@8.1.1) + jest-runtime: 30.5.2(supports-color@8.1.1) + jest-snapshot: 30.5.2(supports-color@8.1.1) + jest-util: 30.5.1 + jest-validate: 30.5.1 + jest-watcher: 30.5.2 + pretty-format: 30.5.1 + slash: 3.0.0 + transitivePeerDependencies: + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + + '@jest/create-cache-key-function@29.7.0': + dependencies: + '@jest/types': 29.6.3 + + '@jest/create-cache-key-function@30.5.1': + dependencies: + '@jest/types': 30.5.1 + + '@jest/diff-sequences@30.5.0': {} + + '@jest/environment-jsdom-abstract@30.5.2(@types/jsdom@21.1.7)(jsdom@26.1.0(supports-color@8.1.1))': + dependencies: + '@jest/environment': 30.5.2 + '@jest/fake-timers': 30.5.2 + '@jest/types': 30.5.1 + '@types/jsdom': 21.1.7 + '@types/node': 26.6.6 + jest-mock: 30.5.2 + jest-util: 30.5.1 + jsdom: 26.1.0(supports-color@8.1.1) + + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 26.6.6 + jest-mock: 29.7.0 + + '@jest/environment@30.5.2': + dependencies: + '@jest/fake-timers': 30.5.2 + '@jest/types': 30.5.1 + '@types/node': 26.6.6 + jest-mock: 30.5.2 + + '@jest/expect-utils@30.5.2': + dependencies: + '@jest/get-type': 30.5.0 + + '@jest/expect@30.5.2(supports-color@8.1.1)': + dependencies: + expect: 30.5.2 + jest-snapshot: 30.5.2(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@jest/fake-timers@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 26.6.6 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + '@jest/fake-timers@30.5.2': + dependencies: + '@jest/types': 30.5.1 + '@sinonjs/fake-timers': 15.4.0 + '@types/node': 26.6.6 + jest-message-util: 30.5.1 + jest-mock: 30.5.2 + jest-util: 30.5.1 + + '@jest/get-type@30.5.0': {} + + '@jest/globals@30.5.2(supports-color@8.1.1)': + dependencies: + '@jest/environment': 30.5.2 + '@jest/expect': 30.5.2(supports-color@8.1.1) + '@jest/types': 30.5.1 + jest-mock: 30.5.2 + transitivePeerDependencies: + - supports-color + + '@jest/pattern@30.5.0': + dependencies: + '@types/node': 26.6.6 + jest-regex-util: 30.5.0 + + '@jest/reporters@30.5.2(supports-color@8.1.1)': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 30.5.2 + '@jest/test-result': 30.5.2 + '@jest/transform': 30.5.2(supports-color@8.1.1) + '@jest/types': 30.5.1 + '@jridgewell/trace-mapping': 0.3.31 + '@types/node': 26.6.6 + chalk: 4.1.2 + collect-v8-coverage: 1.0.3 + exit-x: 0.2.2 + glob: 13.0.6 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3(supports-color@8.1.1) + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6(supports-color@8.1.1) + istanbul-reports: 3.2.0 + jest-message-util: 30.5.1 + jest-util: 30.5.1 + jest-worker: 30.5.1 + slash: 3.0.0 + string-length: 4.0.2 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.12 + + '@jest/schemas@30.5.0': + dependencies: + '@sinclair/typebox': 0.34.52 + + '@jest/snapshot-utils@30.5.1': + dependencies: + '@jest/types': 30.5.1 + chalk: 4.1.2 + graceful-fs: 4.2.11 + natural-compare: 1.4.0 + + '@jest/source-map@30.5.2': + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + callsites: 3.1.0 + convert-source-map: 2.0.0 + graceful-fs: 4.2.11 + + '@jest/test-result@30.5.2': + dependencies: + '@jest/console': 30.5.2 + '@jest/types': 30.5.1 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.3 + + '@jest/test-sequencer@30.5.2': + dependencies: + '@jest/test-result': 30.5.2 + graceful-fs: 4.2.11 + jest-haste-map: 30.5.1 + slash: 3.0.0 + + '@jest/transform@29.7.0(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.31 + babel-plugin-istanbul: 6.1.1(supports-color@8.1.1) + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.8 + pirates: 4.0.7 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + + '@jest/transform@30.5.2(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@jest/types': 30.5.1 + '@jridgewell/trace-mapping': 0.3.31 + babel-plugin-istanbul: 8.0.0(supports-color@8.1.1) + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 30.5.1 + jest-regex-util: 30.5.0 + jest-util: 30.5.1 + pirates: 4.0.7 + slash: 3.0.0 + write-file-atomic: 5.0.1 + transitivePeerDependencies: + - supports-color + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 26.6.6 + '@types/yargs': 17.0.35 + chalk: 4.1.2 + + '@jest/types@30.5.1': + dependencies: + '@jest/pattern': 30.5.0 + '@jest/schemas': 30.5.0 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 26.6.6 + '@types/yargs': 17.0.35 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/source-map@0.3.11': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/sourcemap-codec@1.6.0': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.6.0 + + '@napi-rs/wasm-runtime@1.2.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.4 + optional: true + + '@noxcturnal/noxcturnal-darwin-arm64@0.1.11': + optional: true + + '@noxcturnal/noxcturnal-darwin-x64@0.1.11': + optional: true + + '@noxcturnal/noxcturnal-linux-arm64-gnu@0.1.11': + optional: true + + '@noxcturnal/noxcturnal-linux-arm64-musl@0.1.11': + optional: true + + '@noxcturnal/noxcturnal-linux-x64-gnu@0.1.11': + optional: true + + '@noxcturnal/noxcturnal-linux-x64-musl@0.1.11': + optional: true + + '@noxcturnal/noxcturnal-win32-arm64-msvc@0.1.11': + optional: true + + '@noxcturnal/noxcturnal-win32-x64-msvc@0.1.11': + optional: true + + '@oxc-project/types@0.154.0': {} + + '@parcel/watcher-android-arm64@2.6.0': + optional: true + + '@parcel/watcher-darwin-arm64@2.6.0': + optional: true + + '@parcel/watcher-darwin-x64@2.6.0': + optional: true + + '@parcel/watcher-freebsd-x64@2.6.0': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.6.0': + optional: true + + '@parcel/watcher-linux-arm-musl@2.6.0': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.6.0': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.6.0': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.6.0': + optional: true + + '@parcel/watcher-linux-x64-musl@2.6.0': + optional: true + + '@parcel/watcher-win32-arm64@2.6.0': + optional: true + + '@parcel/watcher-win32-x64@2.6.0': + optional: true + + '@parcel/watcher@2.6.0': + dependencies: + detect-libc: 2.1.2 + is-glob: 4.0.3 + node-addon-api: 7.1.1 + picomatch: 4.0.7 + optionalDependencies: + '@parcel/watcher-android-arm64': 2.6.0 + '@parcel/watcher-darwin-arm64': 2.6.0 + '@parcel/watcher-darwin-x64': 2.6.0 + '@parcel/watcher-freebsd-x64': 2.6.0 + '@parcel/watcher-linux-arm-glibc': 2.6.0 + '@parcel/watcher-linux-arm-musl': 2.6.0 + '@parcel/watcher-linux-arm64-glibc': 2.6.0 + '@parcel/watcher-linux-arm64-musl': 2.6.0 + '@parcel/watcher-linux-x64-glibc': 2.6.0 + '@parcel/watcher-linux-x64-musl': 2.6.0 + '@parcel/watcher-win32-arm64': 2.6.0 + '@parcel/watcher-win32-x64': 2.6.0 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.3.6': {} + + '@radix-ui/primitive@1.2.0': {} + + '@radix-ui/react-collection@1.2.0(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-primitive': 2.2.0(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.0))(react@19.3.0) + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.1(react@19.3.0) + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-compose-refs@1.1.5(@types/react@19.3.0)(react@19.3.0)': + dependencies: + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-context@1.3.0(@types/react@19.3.0)(react@19.3.0)': + dependencies: + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-direction@1.2.0(@types/react@19.3.0)(react@19.3.0)': + dependencies: + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-id@1.1.4(@types/react@19.3.0)(react@19.3.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-presence@1.1.11(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.1(react@19.3.0) + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-primitive@2.2.0(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.1(react@19.3.0) + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-roving-focus@1.2.1(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-collection': 1.2.0(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.0))(react@19.3.0) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-primitive': 2.2.0(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.1(react@19.3.0) + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-slot@1.5.0(@types/react@19.3.0)(react@19.3.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-tabs@1.2.1(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-presence': 1.1.11(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.2.0(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.0))(react@19.3.0) + '@radix-ui/react-roving-focus': 1.2.1(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.1(react@19.3.0) + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-callback-ref@1.1.5(@types/react@19.3.0)(react@19.3.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-controllable-state@1.3.0(@types/react@19.3.0)(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-effect-event@0.0.5(@types/react@19.3.0)(react@19.3.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-is-hydrated@0.1.3(@types/react@19.3.0)(react@19.3.0)': + dependencies: + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-layout-effect@1.1.4(@types/react@19.3.0)(react@19.3.0)': + dependencies: + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@react-native-masked-view/masked-view@0.3.2(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)': + dependencies: + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + + '@react-native/asset-utils@0.88.1': {} + + '@react-native/babel-plugin-codegen@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/traverse': 7.29.10(supports-color@8.1.1) + '@react-native/codegen': 0.88.1(@babel/core@7.29.7(supports-color@8.1.1)) + transitivePeerDependencies: + - '@babel/core' + - supports-color + + '@react-native/babel-preset@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/plugin-proposal-export-default-from': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-export-default-from': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-async-generator-functions': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-async-to-generator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-block-scoping': 7.29.11(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-classes': 7.29.11(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-flow-strip-types': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-for-of': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-optional-catch-binding': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-private-methods': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-private-property-in-object': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-react-display-name': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-regenerator': 7.29.8(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-runtime': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-typescript': 7.29.9(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@react-native/babel-plugin-codegen': 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.29.7(supports-color@8.1.1)) + flow-parser: 0.327.0 + react-refresh: 0.14.2 + transitivePeerDependencies: + - supports-color + + '@react-native/codegen@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/parser': 7.29.11 + flow-parser: 0.327.0 + invariant: 2.2.4 + nullthrows: 1.1.1 + tinyglobby: 0.2.17 + yargs: 17.7.3 + + '@react-native/community-cli-plugin@0.88.1(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@react-native/asset-utils': 0.88.1 + '@react-native/dev-middleware': 0.88.1(supports-color@8.1.1) + commander: 12.1.0 + debug: 4.4.3(supports-color@8.1.1) + invariant: 2.2.4 + metro: 0.87.2(supports-color@8.1.1) + semver: 7.8.5 + optionalDependencies: + '@react-native/metro-config': 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@react-native/debugger-frontend@0.88.1': {} + + '@react-native/debugger-shell@0.88.1(supports-color@8.1.1)': + dependencies: + cross-spawn: 7.0.6 + debug: 4.4.3(supports-color@8.1.1) + fb-dotslash: 0.5.8 + transitivePeerDependencies: + - supports-color + + '@react-native/dev-middleware@0.88.1(supports-color@8.1.1)': + dependencies: + '@isaacs/ttlcache': 1.4.1 + '@react-native/debugger-frontend': 0.88.1 + '@react-native/debugger-shell': 0.88.1(supports-color@8.1.1) + connect: 3.7.0(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) + invariant: 2.2.4 + nullthrows: 1.1.1 + open: 8.4.2 + serve-static: 1.16.3(supports-color@8.1.1) + ws: 7.5.13 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@react-native/gradle-plugin@0.88.1': {} + + '@react-native/jest-preset@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)': + dependencies: + '@jest/create-cache-key-function': 29.7.0 + '@react-native/js-polyfills': 0.88.1 + babel-jest: 29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + jest-environment-node: 29.7.0 + react: 19.3.0 + regenerator-runtime: 0.13.11 + transitivePeerDependencies: + - '@babel/core' + - supports-color + + '@react-native/js-polyfills@0.88.1': {} + + '@react-native/metro-babel-transformer@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@react-native/babel-preset': 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + flow-parser: 0.327.0 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + '@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1)': + dependencies: + '@react-native/js-polyfills': 0.88.1 + '@react-native/metro-babel-transformer': 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + metro-config: 0.87.2(supports-color@8.1.1) + metro-runtime: 0.87.2 + transitivePeerDependencies: + - '@babel/core' + - bufferutil + - supports-color + - utf-8-validate + + '@react-native/normalize-colors@0.88.1': {} + + '@react-native/virtualized-lists@0.88.1(@types/react@19.3.0)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)': + dependencies: + invariant: 2.2.4 + nullthrows: 1.1.1 + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + optionalDependencies: + '@types/react': 19.3.0 + + '@sinclair/typebox@0.27.12': {} + + '@sinclair/typebox@0.34.52': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@10.3.0': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@sinonjs/fake-timers@15.4.0': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@tybys/wasm-util@0.10.4': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.11 + '@babel/types': 7.29.11 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.11 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.11 + '@babel/types': 7.29.11 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.11 + + '@types/emscripten@1.41.6': {} + + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 26.6.6 + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@30.0.0': + dependencies: + expect: 30.5.2 + pretty-format: 30.5.1 + + '@types/jsdom@21.1.7': + dependencies: + '@types/node': 26.6.6 + '@types/tough-cookie': 4.0.5 + parse5: 7.3.0 + + '@types/node@26.6.6': + dependencies: + undici-types: 8.9.0 + + '@types/react-reconciler@0.33.1(@types/react@19.3.0)': + dependencies: + '@types/react': 19.3.0 + + '@types/react-test-renderer@19.3.0': + dependencies: + '@types/react': 19.3.0 + + '@types/react@19.3.0': + dependencies: + csstype: 3.2.3 + + '@types/stack-utils@2.0.3': {} + + '@types/tough-cookie@4.0.5': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.35': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@ungap/structured-clone@1.4.0': {} + + '@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-freebsd-x64@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-loong64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-openharmony-arm64@1.12.2': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.12.2': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.2.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.12.2': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.12.2': + optional: true + + '@xmldom/xmldom@0.8.15': {} + + '@xmldom/xmldom@0.9.12': {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + accepts@2.0.0: + dependencies: + mime-types: 3.0.2 + negotiator: 1.1.0 + + acorn@8.19.0: {} + + agent-base@7.1.4: {} + + agent-cli-detector@0.1.7: {} + + anser@1.4.10: {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-escapes@7.3.0: + dependencies: + environment: 1.1.0 + + ansi-regex@4.1.1: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.4.0: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.3: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.2 + + arg@5.0.2: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + asap@2.0.6: {} + + babel-jest@29.7.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@jest/transform': 29.7.0(supports-color@8.1.1) + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1(supports-color@8.1.1) + babel-preset-jest: 29.6.3(@babel/core@7.29.7(supports-color@8.1.1)) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-jest@30.5.2(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@jest/transform': 30.5.2(supports-color@8.1.1) + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 8.0.0(supports-color@8.1.1) + babel-preset-jest: 30.5.0(@babel/core@7.29.7(supports-color@8.1.1)) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-istanbul@6.1.1(supports-color@8.1.1): + dependencies: + '@babel/helper-plugin-utils': 7.29.7 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.6 + istanbul-lib-instrument: 5.2.1(supports-color@8.1.1) + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-istanbul@8.0.0(supports-color@8.1.1): + dependencies: + '@babel/helper-plugin-utils': 7.29.7 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.6 + istanbul-lib-instrument: 6.0.3(supports-color@8.1.1) + test-exclude: 7.0.2 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@29.6.3: + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.11 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.28.0 + + babel-plugin-jest-hoist@30.5.0: + dependencies: + '@types/babel__core': 7.20.5 + + babel-plugin-polyfill-corejs2@0.4.17(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1): + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + core-js-compat: 3.51.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + babel-plugin-react-compiler@1.0.0: + dependencies: + '@babel/types': 7.29.11 + + babel-plugin-react-native-web@0.21.4: {} + + babel-plugin-syntax-hermes-parser@0.36.1: + dependencies: + hermes-parser: 0.36.1 + + babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.29.7(supports-color@8.1.1)): + dependencies: + '@babel/plugin-syntax-flow': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + transitivePeerDependencies: + - '@babel/core' + + babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.7(supports-color@8.1.1)): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-import-attributes': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.7(supports-color@8.1.1)) + + babel-preset-expo@58.0.22(@babel/core@7.29.7(supports-color@8.1.1))(@babel/runtime@7.29.10)(expo@58.0.21)(react-refresh@0.14.2)(supports-color@8.1.1): + dependencies: + '@babel/generator': 7.29.8 + '@babel/helper-module-imports': 7.29.7(supports-color@8.1.1) + '@babel/plugin-proposal-decorators': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-proposal-export-default-from': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-export-default-from': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-async-generator-functions': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-async-to-generator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-block-scoping': 7.29.11(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-class-static-block': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-classes': 7.29.11(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-export-namespace-from': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-flow-strip-types': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-for-of': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-logical-assignment-operators': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-object-rest-spread': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-optional-catch-binding': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-private-methods': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-private-property-in-object': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-react-display-name': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-react-jsx-development': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-react-pure-annotations': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-runtime': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-typescript': 7.29.9(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@react-native/babel-plugin-codegen': 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + babel-plugin-react-compiler: 1.0.0 + babel-plugin-react-native-web: 0.21.4 + babel-plugin-syntax-hermes-parser: 0.36.1 + babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.29.7(supports-color@8.1.1)) + debug: 4.4.3(supports-color@8.1.1) + react-refresh: 0.14.2 + optionalDependencies: + '@babel/runtime': 7.29.10 + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + transitivePeerDependencies: + - '@babel/core' + - supports-color + + babel-preset-jest@29.6.3(@babel/core@7.29.7(supports-color@8.1.1)): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7(supports-color@8.1.1)) + + babel-preset-jest@30.5.0(@babel/core@7.29.7(supports-color@8.1.1)): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + babel-plugin-jest-hoist: 30.5.0 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7(supports-color@8.1.1)) + + badgin@1.2.3: {} + + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + + barcode-detector@3.2.3(@types/emscripten@1.41.6): + dependencies: + zxing-wasm: 3.1.6(@types/emscripten@1.41.6) + transitivePeerDependencies: + - '@types/emscripten' + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.11.34: {} + + big-integer@1.6.52: {} + + bplist-creator@0.1.0: + dependencies: + stream-buffers: 2.2.0 + + bplist-parser@0.3.1: + dependencies: + big-integer: 1.6.52 + + bplist-parser@0.3.2: + dependencies: + big-integer: 1.6.52 + + brace-expansion@1.1.21: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.1.7: + dependencies: + balanced-match: 1.0.2 + + brace-expansion@5.0.12: + dependencies: + balanced-match: 4.0.4 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.29.5: + dependencies: + baseline-browser-mapping: 2.11.34 + caniuse-lite: 1.0.30001819 + electron-to-chromium: 1.5.467 + node-releases: 2.0.60 + update-browserslist-db: 1.3.4(browserslist@4.29.5) + + bser@2.1.2: + dependencies: + node-int64: 0.4.0 + + buffer-from@1.1.2: {} + + bytes@3.1.2: {} + + callsites@3.1.0: {} + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001819: {} + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.6.2: {} + + char-regex@1.0.2: {} + + ci-info@3.9.0: {} + + ci-info@4.4.0: {} + + cjs-module-lexer@2.3.0: {} + + cli-cursor@2.1.0: + dependencies: + restore-cursor: 2.0.0 + + cli-spinners@2.9.2: {} + + client-only@0.0.1: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone@1.0.4: {} + + co@4.6.0: {} + + collect-v8-coverage@1.0.3: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.4 + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + + commander@12.1.0: {} + + commander@2.20.3: {} + + commander@7.2.0: {} + + compressible@2.0.18: + dependencies: + mime-db: 1.54.0 + + compression@1.8.2(supports-color@8.1.1): + dependencies: + bytes: 3.1.2 + compressible: 2.0.18 + debug: 2.6.9(supports-color@8.1.1) + destroy: 1.2.0 + negotiator: 0.6.4 + on-headers: 1.1.0 + safe-buffer: 5.2.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + concat-map@0.0.1: {} + + connect@3.7.0(supports-color@8.1.1): + dependencies: + debug: 2.6.9(supports-color@8.1.1) + finalhandler: 1.1.2(supports-color@8.1.1) + parseurl: 1.3.3 + utils-merge: 1.0.1 + transitivePeerDependencies: + - supports-color + + content-type@2.1.0: {} + + convert-source-map@2.0.0: {} + + core-js-compat@3.51.0: + dependencies: + browserslist: 4.29.5 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + cssstyle@4.6.0: + dependencies: + '@asamuzakjp/css-color': 3.2.0 + rrweb-cssom: 0.8.0 + + csstype@3.2.3: {} + + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + + debug@2.6.9(supports-color@8.1.1): + dependencies: + ms: 2.0.0 + optionalDependencies: + supports-color: 8.1.1 + + debug@3.2.7(supports-color@8.1.1): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 + + debug@4.4.3(supports-color@8.1.1): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 + + decimal.js@10.6.0: {} + + dedent@1.7.2: {} + + deepmerge@4.3.1: {} + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + define-lazy-prop@2.0.0: {} + + depd@2.0.0: {} + + destroy@1.2.0: {} + + detect-libc@2.1.2: {} + + detect-newline@3.1.0: {} + + dnssd-advertise@1.1.6: {} + + eastasianwidth@0.2.0: {} + + ee-first@1.1.1: {} + + electron-to-chromium@1.5.467: {} + + emittery@0.13.1: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + entities@6.0.1: {} + + environment@1.1.0: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + error-stack-parser@2.1.4: + dependencies: + stackframe: 1.3.4 + + es-errors@1.3.0: {} + + es-module-lexer@2.3.2: {} + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@2.0.0: {} + + esprima@4.0.1: {} + + etag@1.8.1: {} + + event-target-shim@5.0.1: {} + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + exit-x@0.2.2: {} + + expect@30.5.2: + dependencies: + '@jest/expect-utils': 30.5.2 + '@jest/get-type': 30.5.0 + jest-matcher-utils: 30.5.2 + jest-message-util: 30.5.1 + jest-mock: 30.5.2 + jest-util: 30.5.1 + + expo-application@58.1.2(expo@58.0.21): + dependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + + expo-asset@58.0.19(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3): + dependencies: + '@expo/image-utils': 0.12.6(supports-color@8.1.1)(typescript@6.0.3) + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + expo-constants: 58.0.14(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + - typescript + + expo-camera@58.0.14(@types/emscripten@1.41.6)(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0): + dependencies: + barcode-detector: 3.2.3(@types/emscripten@1.41.6) + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + transitivePeerDependencies: + - '@types/emscripten' + + expo-clipboard@58.0.4(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0): + dependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + + expo-constants@58.0.14(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3): + dependencies: + '@expo/env': 2.5.3(supports-color@8.1.1) + '@expo/require-utils': 58.0.5(supports-color@8.1.1)(typescript@6.0.3) + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + - typescript + + expo-crypto@58.0.7(expo@58.0.21): + dependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + + expo-device@58.0.5(expo@58.0.21): + dependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + ua-parser-js: 0.7.41 + + expo-file-system@58.0.13(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1)): + dependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + + expo-font@58.0.11(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0): + dependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + + expo-glass-effect@58.0.5(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0): + dependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + + expo-haptics@58.0.7(expo@58.0.21): + dependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + + expo-keep-awake@58.0.3(expo@58.0.21)(react@19.3.0): + dependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + react: 19.3.0 + + expo-linking@58.0.15(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3): + dependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + expo-constants: 58.0.14(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + invariant: 2.2.4 + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + - typescript + + expo-modules-autolinking@58.0.16(supports-color@8.1.1)(typescript@6.0.3): + dependencies: + '@expo/platforms': 58.0.1 + '@expo/require-utils': 58.0.5(supports-color@8.1.1)(typescript@6.0.3) + '@expo/spawn-async': 1.8.0 + chalk: 4.1.2 + commander: 7.2.0 + transitivePeerDependencies: + - supports-color + - typescript + + expo-modules-cli@0.4.0: + dependencies: + '@babel/parser': 7.29.11 + arg: 5.0.2 + + expo-modules-core@58.0.28(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0): + dependencies: + expo-modules-jsi: 58.0.21(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1)) + expo-modules-macros: 0.27.1 + invariant: 2.2.4 + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + optionalDependencies: + react-native-worklets: 0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1) + + expo-modules-jsi@58.0.21(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1)): + dependencies: + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + + expo-modules-macros@0.27.1: + optionalDependencies: + '@expo/modules-macros-linux-arm64': 0.27.1 + '@expo/modules-macros-linux-x64': 0.27.1 + '@expo/modules-macros-win32-arm64': 0.27.1 + '@expo/modules-macros-win32-x64': 0.27.1 + + expo-notifications@58.1.7(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3): + dependencies: + '@expo/image-utils': 0.12.6(supports-color@8.1.1)(typescript@6.0.3) + abort-controller: 3.0.0 + badgin: 1.2.3 + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + expo-application: 58.1.2(expo@58.0.21) + expo-constants: 58.0.14(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + - typescript + + expo-router@58.0.28(01c662b7665e4b62efc6a8f6b7abec47): + dependencies: + '@expo/log-box': 58.0.13(@expo/dom-webview@58.0.2)(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + '@expo/metro-runtime': 58.0.15(@expo/log-box@58.0.13)(expo@58.0.21)(react-dom@19.3.1(react@19.3.0))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + '@expo/schema-utils': 58.0.2 + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-tabs': 1.2.1(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.0))(react@19.3.0) + '@react-native-masked-view/masked-view': 0.3.2(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + '@react-native/normalize-colors': 0.88.1 + client-only: 0.0.1 + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + expo-constants: 58.0.14(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + expo-glass-effect: 58.0.5(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + expo-linking: 58.0.15(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + expo-server: 58.0.6 + expo-status-bar: 58.0.4(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + nanoid: 3.3.20 + react: 19.3.0 + react-fast-compare: 3.2.2 + react-is: 19.3.1 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + react-native-drawer-layout: 4.2.12(9c740f22a48595961eca6d5a9fad23af) + react-native-safe-area-context: 5.10.1(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + react-native-screens: 4.30.1(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + server-only: 0.0.1 + sf-symbols-typescript: 2.2.0 + standard-navigation: 0.0.5 + optionalDependencies: + react-dom: 19.3.1(react@19.3.0) + react-native-gesture-handler: 3.4.0(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + react-native-reanimated: 4.7.1(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + react-native-worklets: 0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1) + transitivePeerDependencies: + - '@types/react' + - '@types/react-dom' + + expo-secure-store@58.0.2(expo@58.0.21): + dependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + + expo-server@58.0.6: {} + + expo-splash-screen@58.0.12(expo@58.0.21)(supports-color@8.1.1)(typescript@6.0.3): + dependencies: + '@expo/config-plugins': 58.0.11(supports-color@8.1.1)(typescript@6.0.3) + '@expo/image-utils': 0.12.6(supports-color@8.1.1)(typescript@6.0.3) + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + xml2js: 0.6.0 + transitivePeerDependencies: + - supports-color + - typescript + + expo-status-bar@58.0.4(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0): + dependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + + expo@58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3): + dependencies: + '@babel/runtime': 7.29.10 + '@expo/cli': 58.1.17(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.15)(expo-constants@58.0.14)(expo-font@58.0.11(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0))(expo-router@58.0.28)(expo@58.0.21)(react-dom@19.3.1(react@19.3.0))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + '@expo/config': 58.0.9(supports-color@8.1.1)(typescript@6.0.3) + '@expo/config-plugins': 58.0.11(supports-color@8.1.1)(typescript@6.0.3) + '@expo/devtools': 58.0.2(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + '@expo/dom-webview': 58.0.2(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + '@expo/fingerprint': 0.21.7(supports-color@8.1.1) + '@expo/local-build-cache-provider': 58.0.9(supports-color@8.1.1)(typescript@6.0.3) + '@expo/log-box': 58.0.13(@expo/dom-webview@58.0.2)(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + '@expo/log-box-utils': 58.0.2 + '@expo/metro': 58.0.0(supports-color@8.1.1) + '@expo/metro-config': 58.0.19(expo@58.0.21)(supports-color@8.1.1)(typescript@6.0.3) + '@ungap/structured-clone': 1.4.0 + babel-preset-expo: 58.0.22(@babel/core@7.29.7(supports-color@8.1.1))(@babel/runtime@7.29.10)(expo@58.0.21)(react-refresh@0.14.2)(supports-color@8.1.1) + expo-asset: 58.0.19(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + expo-constants: 58.0.14(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(supports-color@8.1.1)(typescript@6.0.3) + expo-file-system: 58.0.13(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1)) + expo-font: 58.0.11(expo@58.0.21)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + expo-keep-awake: 58.0.3(expo@58.0.21)(react@19.3.0) + expo-modules-autolinking: 58.0.16(supports-color@8.1.1)(typescript@6.0.3) + expo-modules-cli: 0.4.0 + expo-modules-core: 58.0.28(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + pretty-format: 29.7.0 + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + react-refresh: 0.14.2 + whatwg-url-minimum: 0.2.0 + optionalDependencies: + '@expo/metro-runtime': 58.0.15(@expo/log-box@58.0.13)(expo@58.0.21)(react-dom@19.3.1(react@19.3.0))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + react-dom: 19.3.1(react@19.3.0) + transitivePeerDependencies: + - '@babel/core' + - bufferutil + - expo-router + - expo-widgets + - react-native-worklets + - react-server-dom-webpack + - supports-color + - typescript + - utf-8-validate + + exponential-backoff@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fb-dotslash@0.5.8: {} + + fb-watchman@2.0.4: + dependencies: + bser: 2.1.2 + + fdir@6.5.0(picomatch@4.0.7): + optionalDependencies: + picomatch: 4.0.7 + + fetch-nodeshim@0.4.10: {} + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.1.2(supports-color@8.1.1): + dependencies: + debug: 2.6.9(supports-color@8.1.1) + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + flow-enums-runtime@0.0.6: {} + + flow-estree@0.327.0: {} + + flow-estree@0.331.0: {} + + flow-estree@0.336.0: {} + + flow-parser@0.327.0: + dependencies: + flow-estree: 0.327.0 + + flow-parser@0.331.0: + dependencies: + flow-estree: 0.331.0 + + flow-parser@0.336.0: + dependencies: + flow-estree: 0.336.0 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + fresh@0.5.2: {} + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-package-type@0.1.0: {} + + get-stream@6.0.1: {} + + getenv@2.0.0: {} + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@13.0.6: + dependencies: + minimatch: 10.2.6 + minipass: 7.1.3 + path-scurry: 2.0.2 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.5 + once: 1.4.0 + path-is-absolute: 1.0.1 + + graceful-fs@4.2.11: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + hermes-compiler@260318099.0.5: {} + + hermes-estree@0.36.1: {} + + hermes-parser@0.36.1: + dependencies: + hermes-estree: 0.36.1 + + hosted-git-info@7.0.2: + dependencies: + lru-cache: 10.4.3 + + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + + html-escaper@2.0.2: {} + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + http-proxy-agent@7.0.2(supports-color@8.1.1): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6(supports-color@8.1.1): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + human-signals@2.1.0: {} + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ignore@5.3.2: {} + + import-local@3.2.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + imurmurhash@0.1.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + invariant@2.2.4: + dependencies: + loose-envify: 1.4.0 + + is-arrayish@0.2.1: {} + + is-arrayish@0.3.4: {} + + is-core-module@2.17.0: + dependencies: + hasown: 2.0.4 + + is-docker@2.2.1: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-generator-fn@2.1.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-potential-custom-element-name@1.0.1: {} + + is-stream@2.0.1: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isexe@2.0.0: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@5.2.1(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/parser': 7.29.11 + '@istanbuljs/schema': 0.1.6 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-instrument@6.0.3(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/parser': 7.29.11 + '@istanbuljs/schema': 0.1.6 + istanbul-lib-coverage: 3.2.2 + semver: 7.8.5 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@5.0.6(supports-color@8.1.1): + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + debug: 4.4.3(supports-color@8.1.1) + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jest-changed-files@30.5.1: + dependencies: + execa: 5.1.1 + jest-util: 30.5.1 + p-limit: 3.1.0 + + jest-circus@30.5.2(supports-color@8.1.1): + dependencies: + '@jest/environment': 30.5.2 + '@jest/expect': 30.5.2(supports-color@8.1.1) + '@jest/test-result': 30.5.2 + '@jest/types': 30.5.1 + '@types/node': 26.6.6 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.7.2 + is-generator-fn: 2.1.0 + jest-each: 30.5.2 + jest-matcher-utils: 30.5.2 + jest-message-util: 30.5.1 + jest-runtime: 30.5.2(supports-color@8.1.1) + jest-snapshot: 30.5.2(supports-color@8.1.1) + jest-util: 30.5.1 + p-limit: 3.1.0 + pretty-format: 30.5.1 + pure-rand: 7.0.1 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-cli@30.5.2(@types/node@26.6.6)(supports-color@8.1.1): + dependencies: + '@jest/core': 30.5.2(supports-color@8.1.1) + '@jest/test-result': 30.5.2 + '@jest/types': 30.5.1 + chalk: 4.1.2 + exit-x: 0.2.2 + import-local: 3.2.0 + jest-config: 30.5.2(@types/node@26.6.6)(supports-color@8.1.1) + jest-util: 30.5.1 + jest-validate: 30.5.1 + yargs: 17.7.3 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + + jest-config@30.5.2(@types/node@26.6.6)(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@jest/get-type': 30.5.0 + '@jest/pattern': 30.5.0 + '@jest/test-sequencer': 30.5.2 + '@jest/types': 30.5.1 + babel-jest: 30.5.2(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + chalk: 4.1.2 + ci-info: 4.4.0 + deepmerge: 4.3.1 + glob: 13.0.6 + graceful-fs: 4.2.11 + jest-circus: 30.5.2(supports-color@8.1.1) + jest-docblock: 30.5.0 + jest-environment-node: 30.5.2 + jest-regex-util: 30.5.0 + jest-resolve: 30.5.1 + jest-runner: 30.5.2(supports-color@8.1.1) + jest-util: 30.5.1 + jest-validate: 30.5.1 + parse-json: 5.2.0 + pretty-format: 30.5.1 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 26.6.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-diff@30.5.2: + dependencies: + '@jest/diff-sequences': 30.5.0 + '@jest/get-type': 30.5.0 + chalk: 4.1.2 + pretty-format: 30.5.1 + + jest-docblock@30.5.0: + dependencies: + detect-newline: 3.1.0 + + jest-each@30.5.2: + dependencies: + '@jest/get-type': 30.5.0 + '@jest/types': 30.5.1 + chalk: 4.1.2 + jest-regex-util: 30.5.0 + jest-util: 30.5.1 + pretty-format: 30.5.1 + + jest-environment-jsdom@30.5.2(supports-color@8.1.1): + dependencies: + '@jest/environment': 30.5.2 + '@jest/environment-jsdom-abstract': 30.5.2(@types/jsdom@21.1.7)(jsdom@26.1.0(supports-color@8.1.1)) + '@types/jsdom': 21.1.7 + jsdom: 26.1.0(supports-color@8.1.1) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jest-environment-node@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 26.6.6 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + jest-environment-node@30.5.2: + dependencies: + '@jest/environment': 30.5.2 + '@jest/fake-timers': 30.5.2 + '@jest/types': 30.5.1 + '@types/node': 26.6.6 + jest-mock: 30.5.2 + jest-util: 30.5.1 + jest-validate: 30.5.1 + + jest-expo@58.0.13(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/jest-preset@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(@types/react@19.3.0)(expo@58.0.21)(jest@30.5.2(@types/node@26.6.6)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1): + dependencies: + '@jest/create-cache-key-function': 30.5.1 + '@jest/globals': 30.5.2(supports-color@8.1.1) + '@react-native/jest-preset': 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1) + babel-jest: 30.5.2(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + jest: 30.5.2(@types/node@26.6.6)(supports-color@8.1.1) + jest-environment-jsdom: 30.5.2(supports-color@8.1.1) + jest-environment-node: 30.5.2 + jest-mock: 30.5.2 + jest-snapshot: 30.5.2(supports-color@8.1.1) + jest-watch-select-projects: 2.0.0 + jest-watch-typeahead: 3.0.1(jest@30.5.2(@types/node@26.6.6)(supports-color@8.1.1)) + json5: 2.2.3 + lodash: 4.18.1 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + server-only: 0.0.1 + stacktrace-js: 2.0.2 + test-renderer: 1.3.0(@types/react@19.3.0)(react@19.3.0) + optionalDependencies: + expo: 58.0.21(@babel/core@7.29.7(supports-color@8.1.1))(@expo/metro-runtime@58.0.15)(expo-router@58.0.28)(react-dom@19.3.1(react@19.3.0))(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1)(typescript@6.0.3) + transitivePeerDependencies: + - '@babel/core' + - '@types/react' + - bufferutil + - canvas + - react + - supports-color + - utf-8-validate + + jest-get-type@29.6.3: {} + + jest-haste-map@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 26.6.6 + anymatch: 3.1.3 + fb-watchman: 2.0.4 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-haste-map@30.5.1: + dependencies: + '@jest/types': 30.5.1 + '@parcel/watcher': 2.6.0 + '@types/node': 26.6.6 + anymatch: 3.1.3 + fb-watchman: 2.0.4 + fdir: 6.5.0(picomatch@4.0.7) + graceful-fs: 4.2.11 + jest-regex-util: 30.5.0 + jest-util: 30.5.1 + jest-worker: 30.5.1 + picomatch: 4.0.7 + + jest-leak-detector@30.5.1: + dependencies: + '@jest/get-type': 30.5.0 + pretty-format: 30.5.1 + + jest-matcher-utils@30.5.2: + dependencies: + '@jest/get-type': 30.5.0 + chalk: 4.1.2 + jest-diff: 30.5.2 + pretty-format: 30.5.1 + + jest-message-util@29.7.0: + dependencies: + '@babel/code-frame': 7.29.7 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-message-util@30.5.1: + dependencies: + '@babel/code-frame': 7.29.7 + '@jest/types': 30.5.1 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-util: 30.5.1 + picomatch: 4.0.7 + pretty-format: 30.5.1 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 26.6.6 + jest-util: 29.7.0 + + jest-mock@30.5.2: + dependencies: + '@jest/expect-utils': 30.5.2 + '@jest/types': 30.5.1 + '@types/node': 26.6.6 + jest-util: 30.5.1 + + jest-regex-util@29.6.3: {} + + jest-regex-util@30.5.0: {} + + jest-resolve-dependencies@30.5.2(supports-color@8.1.1): + dependencies: + jest-regex-util: 30.5.0 + jest-snapshot: 30.5.2(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + jest-resolve@30.5.1: + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 30.5.1 + jest-util: 30.5.1 + jest-validate: 30.5.1 + slash: 3.0.0 + unrs-resolver: 1.12.2 + + jest-runner@30.5.2(supports-color@8.1.1): + dependencies: + '@jest/console': 30.5.2 + '@jest/environment': 30.5.2 + '@jest/source-map': 30.5.2 + '@jest/test-result': 30.5.2 + '@jest/transform': 30.5.2(supports-color@8.1.1) + '@jest/types': 30.5.1 + '@types/node': 26.6.6 + chalk: 4.1.2 + emittery: 0.13.1 + exit-x: 0.2.2 + graceful-fs: 4.2.11 + jest-docblock: 30.5.0 + jest-environment-node: 30.5.2 + jest-haste-map: 30.5.1 + jest-leak-detector: 30.5.1 + jest-message-util: 30.5.1 + jest-resolve: 30.5.1 + jest-runtime: 30.5.2(supports-color@8.1.1) + jest-util: 30.5.1 + jest-watcher: 30.5.2 + jest-worker: 30.5.1 + p-limit: 3.1.0 + transitivePeerDependencies: + - supports-color + + jest-runtime@30.5.2(supports-color@8.1.1): + dependencies: + '@jest/environment': 30.5.2 + '@jest/fake-timers': 30.5.2 + '@jest/globals': 30.5.2(supports-color@8.1.1) + '@jest/source-map': 30.5.2 + '@jest/test-result': 30.5.2 + '@jest/transform': 30.5.2(supports-color@8.1.1) + '@jest/types': 30.5.1 + '@types/node': 26.6.6 + chalk: 4.1.2 + cjs-module-lexer: 2.3.0 + collect-v8-coverage: 1.0.3 + es-module-lexer: 2.3.2 + glob: 13.0.6 + graceful-fs: 4.2.11 + jest-haste-map: 30.5.1 + jest-message-util: 30.5.1 + jest-mock: 30.5.2 + jest-regex-util: 30.5.0 + jest-resolve: 30.5.1 + jest-snapshot: 30.5.2(supports-color@8.1.1) + jest-util: 30.5.1 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + + jest-snapshot@30.5.2(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/generator': 7.29.8 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/types': 7.29.11 + '@jest/expect-utils': 30.5.2 + '@jest/get-type': 30.5.0 + '@jest/snapshot-utils': 30.5.1 + '@jest/transform': 30.5.2(supports-color@8.1.1) + '@jest/types': 30.5.1 + babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7(supports-color@8.1.1)) + chalk: 4.1.2 + expect: 30.5.2 + graceful-fs: 4.2.11 + jest-diff: 30.5.2 + jest-matcher-utils: 30.5.2 + jest-message-util: 30.5.1 + jest-util: 30.5.1 + pretty-format: 30.5.1 + semver: 7.8.5 + synckit: 0.11.13 + transitivePeerDependencies: + - supports-color + + jest-util@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 26.6.6 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.2 + + jest-util@30.5.1: + dependencies: + '@jest/types': 30.5.1 + '@types/node': 26.6.6 + chalk: 4.1.2 + ci-info: 4.4.0 + graceful-fs: 4.2.11 + picomatch: 4.0.7 + + jest-validate@29.7.0: + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + + jest-validate@30.5.1: + dependencies: + '@jest/get-type': 30.5.0 + '@jest/types': 30.5.1 + camelcase: 6.3.0 + chalk: 4.1.2 + leven: 3.1.0 + pretty-format: 30.5.1 + + jest-watch-select-projects@2.0.0: + dependencies: + ansi-escapes: 4.3.2 + chalk: 3.0.0 + prompts: 2.4.2 + + jest-watch-typeahead@3.0.1(jest@30.5.2(@types/node@26.6.6)(supports-color@8.1.1)): + dependencies: + ansi-escapes: 7.3.0 + chalk: 5.6.2 + jest: 30.5.2(@types/node@26.6.6)(supports-color@8.1.1) + jest-regex-util: 30.5.0 + jest-watcher: 30.5.2 + slash: 5.1.0 + string-length: 6.0.0 + strip-ansi: 7.2.0 + + jest-watcher@30.5.2: + dependencies: + '@jest/test-result': 30.5.2 + '@jest/types': 30.5.1 + '@types/node': 26.6.6 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 30.5.1 + string-length: 4.0.2 + + jest-worker@29.7.0: + dependencies: + '@types/node': 26.6.6 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest-worker@30.5.1: + dependencies: + '@types/node': 26.6.6 + '@ungap/structured-clone': 1.4.0 + jest-util: 30.5.1 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest@30.5.2(@types/node@26.6.6)(supports-color@8.1.1): + dependencies: + '@jest/core': 30.5.2(supports-color@8.1.1) + '@jest/types': 30.5.1 + import-local: 3.2.0 + jest-cli: 30.5.2(@types/node@26.6.6)(supports-color@8.1.1) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - esbuild-register + - supports-color + - ts-node + + jimp-compact@0.16.1: {} + + js-tokens@4.0.0: {} + + js-yaml@3.15.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.3.2: + dependencies: + argparse: 2.0.1 + + jsc-safe-url@0.2.4: {} + + jsdom@26.1.0(supports-color@8.1.1): + dependencies: + cssstyle: 4.6.0 + data-urls: 5.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2(supports-color@8.1.1) + https-proxy-agent: 7.0.6(supports-color@8.1.1) + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.28 + parse5: 7.3.0 + rrweb-cssom: 0.8.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 5.1.2 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + ws: 8.22.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsesc@3.1.0: {} + + json-parse-even-better-errors@2.3.1: {} + + json5@2.2.3: {} + + kleur@3.0.3: {} + + lan-network@0.2.1: {} + + leven@3.1.0: {} + + lightningcss-android-arm64@1.33.0: + optional: true + + lightningcss-darwin-arm64@1.33.0: + optional: true + + lightningcss-darwin-x64@1.33.0: + optional: true + + lightningcss-freebsd-x64@1.33.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.33.0: + optional: true + + lightningcss-linux-arm64-gnu@1.33.0: + optional: true + + lightningcss-linux-arm64-musl@1.33.0: + optional: true + + lightningcss-linux-x64-gnu@1.33.0: + optional: true + + lightningcss-linux-x64-musl@1.33.0: + optional: true + + lightningcss-win32-arm64-msvc@1.33.0: + optional: true + + lightningcss-win32-x64-msvc@1.33.0: + optional: true + + lightningcss@1.33.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + + lines-and-columns@1.2.4: {} + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + lodash.debounce@4.0.8: {} + + lodash.throttle@4.1.1: {} + + lodash@4.18.1: {} + + log-symbols@2.2.0: + dependencies: + chalk: 2.4.2 + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lru-cache@10.4.3: {} + + lru-cache@11.5.3: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + make-dir@4.0.0: + dependencies: + semver: 7.8.5 + + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + + memoize-one@5.2.1: {} + + merge-stream@2.0.0: {} + + metro-babel-transformer@0.87.1(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + flow-enums-runtime: 0.0.6 + flow-parser: 0.331.0 + metro-cache-key: 0.87.1 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + metro-babel-transformer@0.87.2(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + flow-enums-runtime: 0.0.6 + flow-parser: 0.336.0 + metro-cache-key: 0.87.2 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + metro-cache-key@0.87.1: + dependencies: + flow-enums-runtime: 0.0.6 + + metro-cache-key@0.87.2: + dependencies: + flow-enums-runtime: 0.0.6 + + metro-cache@0.87.1(supports-color@8.1.1): + dependencies: + exponential-backoff: 3.1.3 + flow-enums-runtime: 0.0.6 + https-proxy-agent: 7.0.6(supports-color@8.1.1) + metro-core: 0.87.1 + transitivePeerDependencies: + - supports-color + + metro-cache@0.87.2(supports-color@8.1.1): + dependencies: + exponential-backoff: 3.1.3 + flow-enums-runtime: 0.0.6 + https-proxy-agent: 7.0.6(supports-color@8.1.1) + metro-core: 0.87.2 + transitivePeerDependencies: + - supports-color + + metro-config@0.87.1(supports-color@8.1.1): + dependencies: + connect: 3.7.0(supports-color@8.1.1) + flow-enums-runtime: 0.0.6 + jest-validate: 29.7.0 + metro: 0.87.1(supports-color@8.1.1) + metro-cache: 0.87.1(supports-color@8.1.1) + metro-core: 0.87.1 + metro-runtime: 0.87.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + metro-config@0.87.2(supports-color@8.1.1): + dependencies: + connect: 3.7.0(supports-color@8.1.1) + flow-enums-runtime: 0.0.6 + jest-validate: 29.7.0 + metro: 0.87.2(supports-color@8.1.1) + metro-cache: 0.87.2(supports-color@8.1.1) + metro-core: 0.87.2 + metro-runtime: 0.87.2 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + metro-core@0.87.1: + dependencies: + flow-enums-runtime: 0.0.6 + lodash.throttle: 4.1.1 + metro-resolver: 0.87.1 + + metro-core@0.87.2: + dependencies: + flow-enums-runtime: 0.0.6 + lodash.throttle: 4.1.1 + metro-resolver: 0.87.2 + + metro-file-map@0.87.1(supports-color@8.1.1): + dependencies: + debug: 4.4.3(supports-color@8.1.1) + fb-watchman: 2.0.4 + flow-enums-runtime: 0.0.6 + graceful-fs: 4.2.11 + invariant: 2.2.4 + jest-worker: 29.7.0 + micromatch: 4.0.8 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + metro-file-map@0.87.2(supports-color@8.1.1): + dependencies: + debug: 4.4.3(supports-color@8.1.1) + fb-watchman: 2.0.4 + flow-enums-runtime: 0.0.6 + invariant: 2.2.4 + jest-worker: 29.7.0 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + metro-minify-terser@0.87.1: + dependencies: + flow-enums-runtime: 0.0.6 + terser: 5.51.2 + + metro-minify-terser@0.87.2: + dependencies: + flow-enums-runtime: 0.0.6 + terser: 5.51.2 + + metro-resolver@0.87.1: + dependencies: + flow-enums-runtime: 0.0.6 + + metro-resolver@0.87.2: + dependencies: + flow-enums-runtime: 0.0.6 + + metro-runtime@0.87.1: + dependencies: + '@babel/runtime': 7.29.10 + flow-enums-runtime: 0.0.6 + + metro-runtime@0.87.2: + dependencies: + '@babel/runtime': 7.29.10 + flow-enums-runtime: 0.0.6 + + metro-source-map@0.87.1(supports-color@8.1.1): + dependencies: + '@babel/traverse': 7.29.10(supports-color@8.1.1) + '@babel/types': 7.29.11 + flow-enums-runtime: 0.0.6 + invariant: 2.2.4 + metro-symbolicate: 0.87.1 + nullthrows: 1.1.1 + ob1: 0.87.1 + source-map: 0.5.7 + vlq: 1.0.1 + transitivePeerDependencies: + - supports-color + + metro-source-map@0.87.2(supports-color@8.1.1): + dependencies: + '@babel/traverse': 7.29.10(supports-color@8.1.1) + '@babel/types': 7.29.11 + flow-enums-runtime: 0.0.6 + invariant: 2.2.4 + metro-symbolicate: 0.87.2 + nullthrows: 1.1.1 + ob1: 0.87.2 + source-map: 0.5.7 + transitivePeerDependencies: + - supports-color + + metro-symbolicate@0.87.1: + dependencies: + flow-enums-runtime: 0.0.6 + invariant: 2.2.4 + metro-source-map: 0.87.1(supports-color@8.1.1) + nullthrows: 1.1.1 + source-map: 0.5.7 + vlq: 1.0.1 + + metro-symbolicate@0.87.2: + dependencies: + flow-enums-runtime: 0.0.6 + invariant: 2.2.4 + metro-source-map: 0.87.2(supports-color@8.1.1) + nullthrows: 1.1.1 + source-map: 0.5.7 + vlq: 1.0.1 + + metro-transform-plugins@0.87.1(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/generator': 7.29.8 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.10(supports-color@8.1.1) + flow-enums-runtime: 0.0.6 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + metro-transform-plugins@0.87.2(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/generator': 7.29.8 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.10(supports-color@8.1.1) + flow-enums-runtime: 0.0.6 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + metro-transform-worker@0.87.1(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/generator': 7.29.8 + '@babel/parser': 7.29.11 + '@babel/types': 7.29.11 + flow-enums-runtime: 0.0.6 + metro: 0.87.1(supports-color@8.1.1) + metro-babel-transformer: 0.87.1(supports-color@8.1.1) + metro-cache: 0.87.1(supports-color@8.1.1) + metro-cache-key: 0.87.1 + metro-minify-terser: 0.87.1 + metro-source-map: 0.87.1(supports-color@8.1.1) + metro-transform-plugins: 0.87.1(supports-color@8.1.1) + nullthrows: 1.1.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + metro-transform-worker@0.87.2(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/generator': 7.29.8 + '@babel/parser': 7.29.11 + '@babel/types': 7.29.11 + flow-enums-runtime: 0.0.6 + metro: 0.87.2(supports-color@8.1.1) + metro-babel-transformer: 0.87.2(supports-color@8.1.1) + metro-cache: 0.87.2(supports-color@8.1.1) + metro-cache-key: 0.87.2 + metro-minify-terser: 0.87.2 + metro-source-map: 0.87.2(supports-color@8.1.1) + metro-transform-plugins: 0.87.2(supports-color@8.1.1) + nullthrows: 1.1.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + metro@0.87.1(supports-color@8.1.1): + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/generator': 7.29.8 + '@babel/parser': 7.29.11 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.10(supports-color@8.1.1) + '@babel/types': 7.29.11 + accepts: 2.0.0 + connect: 3.7.0(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) + error-stack-parser: 2.1.4 + flow-enums-runtime: 0.0.6 + flow-parser: 0.331.0 + graceful-fs: 4.2.11 + invariant: 2.2.4 + jest-worker: 29.7.0 + jsc-safe-url: 0.2.4 + lodash.throttle: 4.1.1 + metro-babel-transformer: 0.87.1(supports-color@8.1.1) + metro-cache: 0.87.1(supports-color@8.1.1) + metro-cache-key: 0.87.1 + metro-config: 0.87.1(supports-color@8.1.1) + metro-core: 0.87.1 + metro-file-map: 0.87.1(supports-color@8.1.1) + metro-resolver: 0.87.1 + metro-runtime: 0.87.1 + metro-source-map: 0.87.1(supports-color@8.1.1) + metro-symbolicate: 0.87.1 + metro-transform-plugins: 0.87.1(supports-color@8.1.1) + metro-transform-worker: 0.87.1(supports-color@8.1.1) + mime-types: 3.0.2 + nullthrows: 1.1.1 + serialize-error: 2.1.0 + source-map: 0.5.7 + throat: 5.0.0 + ws: 7.5.13 + yargs: 17.7.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + metro@0.87.2(supports-color@8.1.1): + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/generator': 7.29.8 + '@babel/parser': 7.29.11 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.10(supports-color@8.1.1) + '@babel/types': 7.29.11 + accepts: 2.0.0 + connect: 3.7.0(supports-color@8.1.1) + debug: 4.4.3(supports-color@8.1.1) + error-stack-parser: 2.1.4 + flow-enums-runtime: 0.0.6 + flow-parser: 0.336.0 + invariant: 2.2.4 + jest-worker: 29.7.0 + jsc-safe-url: 0.2.4 + lodash.throttle: 4.1.1 + metro-babel-transformer: 0.87.2(supports-color@8.1.1) + metro-cache: 0.87.2(supports-color@8.1.1) + metro-cache-key: 0.87.2 + metro-config: 0.87.2(supports-color@8.1.1) + metro-core: 0.87.2 + metro-file-map: 0.87.2(supports-color@8.1.1) + metro-resolver: 0.87.2 + metro-runtime: 0.87.2 + metro-source-map: 0.87.2(supports-color@8.1.1) + metro-symbolicate: 0.87.2 + metro-transform-plugins: 0.87.2(supports-color@8.1.1) + metro-transform-worker: 0.87.2(supports-color@8.1.1) + mime-types: 3.0.2 + nullthrows: 1.1.1 + serialize-error: 2.1.0 + source-map: 0.5.7 + throat: 5.0.0 + ws: 7.5.13 + yargs: 17.7.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + + mime@1.6.0: {} + + mimic-fn@1.2.0: {} + + mimic-fn@2.1.0: {} + + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.12 + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.21 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.1.7 + + minipass@7.1.3: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + multitars@1.0.2: {} + + nanoid@3.3.20: {} + + napi-postinstall@0.3.7: {} + + natural-compare@1.4.0: {} + + negotiator@0.6.3: {} + + negotiator@0.6.4: {} + + negotiator@1.1.0: + dependencies: + content-type: 2.1.0 + + node-addon-api@7.1.1: {} + + node-forge@1.4.2: {} + + node-int64@0.4.0: {} + + node-releases@2.0.60: {} + + normalize-path@3.0.0: {} + + noxcturnal@0.1.11: + dependencies: + '@babel/code-frame': 7.29.7 + '@oxc-project/types': 0.154.0 + optionalDependencies: + '@noxcturnal/noxcturnal-darwin-arm64': 0.1.11 + '@noxcturnal/noxcturnal-darwin-x64': 0.1.11 + '@noxcturnal/noxcturnal-linux-arm64-gnu': 0.1.11 + '@noxcturnal/noxcturnal-linux-arm64-musl': 0.1.11 + '@noxcturnal/noxcturnal-linux-x64-gnu': 0.1.11 + '@noxcturnal/noxcturnal-linux-x64-musl': 0.1.11 + '@noxcturnal/noxcturnal-win32-arm64-msvc': 0.1.11 + '@noxcturnal/noxcturnal-win32-x64-msvc': 0.1.11 + + npm-package-arg@11.0.3: + dependencies: + hosted-git-info: 7.0.2 + proc-log: 4.2.0 + semver: 7.8.5 + validate-npm-package-name: 5.0.1 + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + nullthrows@1.1.1: {} + + nwsapi@2.2.28: {} + + ob1@0.87.1: + dependencies: + flow-enums-runtime: 0.0.6 + + ob1@0.87.2: + dependencies: + flow-enums-runtime: 0.0.6 + + on-finished@2.3.0: + dependencies: + ee-first: 1.1.1 + + on-finished@2.4.2: + dependencies: + ee-first: 1.1.1 + + on-headers@1.1.0: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@2.0.1: + dependencies: + mimic-fn: 1.2.0 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + ora@3.4.0: + dependencies: + chalk: 2.4.2 + cli-cursor: 2.1.0 + cli-spinners: 2.9.2 + log-symbols: 2.2.0 + strip-ansi: 5.2.0 + wcwidth: 1.0.1 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.29.7 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-png@2.1.0: + dependencies: + pngjs: 3.4.0 + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + parseurl@1.3.3: {} + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + + path-scurry@2.0.2: + dependencies: + lru-cache: 11.5.3 + minipass: 7.1.3 + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.7: {} + + pirates@4.0.7: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + plist@3.1.1: + dependencies: + '@xmldom/xmldom': 0.9.12 + base64-js: 1.5.1 + xmlbuilder: 15.1.1 + + pngjs@3.4.0: {} + + postcss@8.5.32: + dependencies: + nanoid: 3.3.20 + picocolors: 1.1.1 + source-map-js: 1.2.2 + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + pretty-format@30.5.1: + dependencies: + '@jest/react-is-18': react-is@18.3.1 + '@jest/react-is-19': react-is@19.3.1 + '@jest/schemas': 30.5.0 + ansi-styles: 5.2.0 + + proc-log@4.2.0: {} + + progress@2.0.3: {} + + promise@8.3.0: + dependencies: + asap: 2.0.6 + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + punycode@2.3.1: {} + + pure-rand@7.0.1: {} + + range-parser@1.2.1: {} + + react-devtools-core@6.1.5: + dependencies: + shell-quote: 1.12.0 + ws: 7.5.13 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + react-dom@19.3.1(react@19.3.0): + dependencies: + react: 19.3.0 + scheduler: 0.28.0 + + react-fast-compare@3.2.2: {} + + react-freeze@1.0.4(react@19.3.0): + dependencies: + react: 19.3.0 + + react-is@18.3.1: {} + + react-is@19.3.1: {} + + react-native-drawer-layout@4.2.12(9c740f22a48595961eca6d5a9fad23af): + dependencies: + color: 4.2.3 + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + react-native-gesture-handler: 3.4.0(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + react-native-reanimated: 4.7.1(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + use-latest-callback: 0.2.6(react@19.3.0) + + react-native-gesture-handler@3.4.0(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0): + dependencies: + '@types/react-test-renderer': 19.3.0 + invariant: 2.2.4 + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + + react-native-is-edge-to-edge@1.3.1(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0): + dependencies: + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + + react-native-reanimated@4.7.1(react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0): + dependencies: + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + react-native-is-edge-to-edge: 1.3.1(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + react-native-worklets: 0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1) + semver: 7.8.5 + + react-native-safe-area-context@5.10.1(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0): + dependencies: + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + + react-native-screens@4.30.1(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0): + dependencies: + react: 19.3.0 + react-freeze: 1.0.4(react@19.3.0) + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + warn-once: 0.1.1 + + react-native-worklets@0.13.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0)(supports-color@8.1.1): + dependencies: + '@babel/core': 7.29.7(supports-color@8.1.1) + '@babel/generator': 7.29.8 + '@babel/plugin-transform-arrow-functions': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-classes': 7.29.11(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/plugin-transform-shorthand-properties': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-template-literals': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1)) + '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + '@babel/traverse': 7.29.10(supports-color@8.1.1) + '@babel/types': 7.29.11 + '@jridgewell/remapping': 2.3.5 + '@react-native/metro-config': 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1) + convert-source-map: 2.0.0 + react: 19.3.0 + react-native: 0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1) + semver: 7.8.5 + whatwg-fetch: 3.6.20 + transitivePeerDependencies: + - supports-color + + react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1): + dependencies: + '@react-native/asset-utils': 0.88.1 + '@react-native/codegen': 0.88.1(@babel/core@7.29.7(supports-color@8.1.1)) + '@react-native/community-cli-plugin': 0.88.1(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(supports-color@8.1.1) + '@react-native/gradle-plugin': 0.88.1 + '@react-native/normalize-colors': 0.88.1 + '@react-native/virtualized-lists': 0.88.1(@types/react@19.3.0)(react-native@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(@react-native/metro-config@0.88.1(@babel/core@7.29.7(supports-color@8.1.1))(supports-color@8.1.1))(@types/react@19.3.0)(react@19.3.0)(supports-color@8.1.1))(react@19.3.0) + anser: 1.4.10 + ansi-regex: 5.0.1 + base64-js: 1.5.1 + flow-enums-runtime: 0.0.6 + flow-parser: 0.327.0 + hermes-compiler: 260318099.0.5 + invariant: 2.2.4 + memoize-one: 5.2.1 + metro-runtime: 0.87.2 + metro-source-map: 0.87.2(supports-color@8.1.1) + nullthrows: 1.1.1 + pretty-format: 29.7.0 + promise: 8.3.0 + react: 19.3.0 + react-devtools-core: 6.1.5 + react-refresh: 0.14.2 + regenerator-runtime: 0.13.11 + scheduler: 0.28.0 + semver: 7.8.5 + stacktrace-parser: 0.1.11 + tinyglobby: 0.2.17 + whatwg-fetch: 3.6.20 + ws: 7.5.13 + yargs: 17.7.3 + optionalDependencies: + '@types/react': 19.3.0 + transitivePeerDependencies: + - '@babel/core' + - '@react-native-community/cli' + - '@react-native/metro-config' + - bufferutil + - supports-color + - utf-8-validate + + react-reconciler@0.34.0(react@19.3.0): + dependencies: + react: 19.3.0 + scheduler: 0.28.0 + + react-refresh@0.14.2: {} + + react@19.3.0: {} + + regenerate-unicode-properties@10.3.0: + dependencies: + regenerate: 1.5.0 + + regenerate@1.5.0: {} + + regenerator-runtime@0.13.11: {} + + regexpu-core@6.5.3: + dependencies: + regenerate: 1.5.0 + regenerate-unicode-properties: 10.3.0 + regjsgen: 0.8.0 + regjsparser: 0.13.4 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.1 + + regjsgen@0.8.0: {} + + regjsparser@0.13.4: + dependencies: + jsesc: 3.1.0 + + require-directory@2.1.1: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + + resolve-from@5.0.0: {} + + resolve-workspace-root@2.0.1: {} + + resolve@1.22.13: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.17.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@2.0.0: + dependencies: + onetime: 2.0.1 + signal-exit: 3.0.7 + + rrweb-cssom@0.8.0: {} + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + sandbox-cli-detector@0.2.0: {} + + sax@1.6.1: {} + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + scheduler@0.28.0: {} + + semver@6.3.1: {} + + semver@7.8.5: {} + + send@0.19.2(supports-color@8.1.1): + dependencies: + debug: 2.6.9(supports-color@8.1.1) + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.2 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serialize-error@2.1.0: {} + + serve-static@1.16.3(supports-color@8.1.1): + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.2(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + server-only@0.0.1: {} + + setprototypeof@1.2.0: {} + + sf-symbols-typescript@2.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shell-quote@1.12.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + simple-plist@1.3.1: + dependencies: + bplist-creator: 0.1.0 + bplist-parser: 0.3.1 + plist: 3.1.1 + + simple-swizzle@0.2.4: + dependencies: + is-arrayish: 0.3.4 + + sisteransi@1.0.5: {} + + slash@3.0.0: {} + + slash@5.1.0: {} + + slugify@1.6.9: {} + + source-map-js@1.2.2: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.5.6: {} + + source-map@0.5.7: {} + + source-map@0.6.1: {} + + sprintf-js@1.0.3: {} + + stack-generator@2.0.10: + dependencies: + stackframe: 1.3.4 + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + stackframe@1.3.4: {} + + stacktrace-gps@3.1.2: + dependencies: + source-map: 0.5.6 + stackframe: 1.3.4 + + stacktrace-js@2.0.2: + dependencies: + error-stack-parser: 2.1.4 + stack-generator: 2.0.10 + stacktrace-gps: 3.1.2 + + stacktrace-parser@0.1.11: + dependencies: + type-fest: 0.7.1 + + standard-navigation@0.0.5: {} + + statuses@1.5.0: {} + + statuses@2.0.2: {} + + stream-buffers@2.2.0: {} + + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + + string-length@6.0.0: + dependencies: + strip-ansi: 7.2.0 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + + strip-ansi@5.2.0: + dependencies: + ansi-regex: 4.1.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.4.0 + + strip-bom@4.0.0: {} + + strip-final-newline@2.0.0: {} + + strip-json-comments@3.1.1: {} + + structured-headers@0.4.1: {} + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-hyperlinks@2.3.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + symbol-tree@3.2.4: {} + + synckit@0.11.13: + dependencies: + '@pkgr/core': 0.3.6 + + tagged-tag@1.0.0: {} + + terminal-link@2.1.1: + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.3.0 + + terser@5.51.2: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.19.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.6 + glob: 7.2.3 + minimatch: 3.1.5 + + test-exclude@7.0.2: + dependencies: + '@istanbuljs/schema': 0.1.6 + glob: 10.5.0 + minimatch: 10.2.6 + + test-renderer@1.3.0(@types/react@19.3.0)(react@19.3.0): + dependencies: + '@types/react-reconciler': 0.33.1(@types/react@19.3.0) + react: 19.3.0 + react-reconciler: 0.34.0(react@19.3.0) + transitivePeerDependencies: + - '@types/react' + + throat@5.0.0: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 + + tldts-core@6.1.86: {} + + tldts@6.1.86: + dependencies: + tldts-core: 6.1.86 + + tmpl@1.0.5: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.1: {} + + toqr@0.1.1: {} + + tough-cookie@5.1.2: + dependencies: + tldts: 6.1.86 + + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + + tslib@2.8.1: + optional: true + + type-detect@4.0.8: {} + + type-fest@0.21.3: {} + + type-fest@0.7.1: {} + + type-fest@5.10.0: + dependencies: + tagged-tag: 1.0.0 + + typescript@6.0.3: {} + + ua-parser-js@0.7.41: {} + + undici-types@8.9.0: {} + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.2.0 + + unicode-match-property-value-ecmascript@2.2.1: {} + + unicode-property-aliases-ecmascript@2.2.0: {} + + unpipe@1.0.0: {} + + unrs-resolver@1.12.2: + dependencies: + napi-postinstall: 0.3.7 + optionalDependencies: + '@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.3.4(browserslist@4.29.5): + dependencies: + browserslist: 4.29.5 + escalade: 3.2.0 + picocolors: 1.1.1 + + use-latest-callback@0.2.6(react@19.3.0): + dependencies: + react: 19.3.0 + + utils-merge@1.0.1: {} + + v8-to-istanbul@9.3.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + + validate-npm-package-name@5.0.1: {} + + vary@1.1.2: {} + + vlq@1.0.1: {} + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + + warn-once@0.1.1: {} + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + + webidl-conversions@7.0.0: {} + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-fetch@3.6.20: {} + + whatwg-mimetype@4.0.0: {} + + whatwg-url-minimum@0.2.0: {} + + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + + wrappy@1.0.2: {} + + write-file-atomic@4.0.2: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + + write-file-atomic@5.0.1: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + + ws@7.5.13: {} + + ws@8.22.0: {} + + xcode@4.0.0: + dependencies: + simple-plist: 1.3.1 + + xml-name-validator@5.0.0: {} + + xml2js@0.6.0: + dependencies: + sax: 1.6.1 + xmlbuilder: 11.0.1 + + xmlbuilder@11.0.1: {} + + xmlbuilder@15.1.1: {} + + xmlchars@2.2.0: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.3: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {} + + zod@3.25.76: {} + + zustand@5.0.16(@types/react@19.3.0)(react@19.3.0): + optionalDependencies: + '@types/react': 19.3.0 + react: 19.3.0 + + zxing-wasm@3.1.6(@types/emscripten@1.41.6): + dependencies: + '@types/emscripten': 1.41.6 + type-fest: 5.10.0 diff --git a/mobile/pnpm-workspace.yaml b/mobile/pnpm-workspace.yaml new file mode 100644 index 000000000..f6df9d5c7 --- /dev/null +++ b/mobile/pnpm-workspace.yaml @@ -0,0 +1,6 @@ +allowBuilds: + esbuild: true + # Prebuilt binaries; their build scripts aren't needed. + "@parcel/watcher": false + unrs-resolver: false +nodeLinker: hoisted diff --git a/mobile/src/app/(tabs)/_layout.tsx b/mobile/src/app/(tabs)/_layout.tsx new file mode 100644 index 000000000..b25693e42 --- /dev/null +++ b/mobile/src/app/(tabs)/_layout.tsx @@ -0,0 +1,47 @@ +import { Redirect, Tabs } from "expo-router"; +import { Text, type ColorValue } from "react-native"; + +import { sessionState } from "@berth/core/derive.ts"; + +import { useStore } from "@/lib/store"; +import { useColors } from "@/lib/theme"; + +// Needs you, Runs and Boxes. With no box paired (and no demo), pairing +// comes first. + +const glyph = (g: string) => + function Icon({ color }: { color: ColorValue }) { + return {g}; + }; + +export default function TabsLayout() { + const c = useColors(); + const boxes = useStore((s) => s.boxes); + const waiting = useStore((s) => + Object.values(s.data).reduce( + (n, d) => n + (d.sessions ?? []).filter((x) => !x.exited && x.agent && sessionState(x) === "waiting").length + (d.runs ?? []).filter((r) => r.status === "waiting_gate").length, + 0, + ), + ); + if (!boxes.length) return ; + return ( + + + + + + ); +} diff --git a/mobile/src/app/(tabs)/boxes.tsx b/mobile/src/app/(tabs)/boxes.tsx new file mode 100644 index 000000000..ce9b9fec7 --- /dev/null +++ b/mobile/src/app/(tabs)/boxes.tsx @@ -0,0 +1,129 @@ +import { router } from "expo-router"; +import { useEffect, useState } from "react"; +import { Alert, Pressable, ScrollView, StyleSheet, Text, View } from "react-native"; + +import { Button, Card, Dot, Note, SectionTitle } from "@/components/ui"; +import { can } from "@/lib/api"; +import { pushChoice, setPush, unregisterBox, type PushChoice } from "@/lib/push"; +import { useStore } from "@/lib/store"; +import { useColors } from "@/lib/theme"; + +// The boxes this phone is paired with, how each is reached, and the +// notifications they send it. Forgetting a box removes it from this phone +// only; turning phone access off is Shipyard's, on the laptop. + +const CHOICES: [PushChoice, string][] = [ + ["off", "Off"], + ["waiting", "Needs you"], + ["waiting+finished", "Needs you and done"], +]; + +export default function Boxes() { + const c = useColors(); + const boxes = useStore((s) => s.boxes); + const data = useStore((s) => s.data); + const demo = useStore((s) => s.demo); + const [choice, setChoice] = useState("off"); + const [busy, setBusy] = useState(false); + const [pushNote, setPushNote] = useState(); + + useEffect(() => { + void pushChoice().then(setChoice); + }, []); + + const choose = async (next: PushChoice) => { + if (demo) return setPushNote("The demo's boxes don't send notifications. Pair your own to get them."); + setBusy(true); + setPushNote(undefined); + try { + const { failed } = await setPush( + next, + boxes.map((box) => ({ box, info: data[box.id]?.info })), + ); + setChoice(next); + const older = boxes.filter((b) => next !== "off" && !can(data[b.id]?.info, "push")); + const notes = [ + ...failed.map((f) => `${f.box.name}: ${f.error}`), + ...older.map((b) => `${b.name} runs an older berthd that can't notify the app; update it from Shipyard.`), + ]; + setPushNote(notes.join("\n") || undefined); + } catch (err) { + setPushNote((err as Error).message); + } finally { + setBusy(false); + } + }; + + const forget = (id: string) => { + const box = boxes.find((b) => b.id === id); + if (!box) return; + Alert.alert(`Forget ${box.name}?`, "This phone stops showing its agents. To stop the box answering phones at all, turn phone access off in Shipyard.", [ + { text: "Cancel", style: "cancel" }, + { + text: "Forget", + style: "destructive", + onPress: () => { + void unregisterBox(box, data[id]?.info).catch(() => undefined); + void useStore.getState().forget(id); + }, + }, + ]); + }; + + return ( + + + + {CHOICES.map(([value, label]) => ( + void choose(value)} + accessibilityRole="button" + accessibilityState={{ selected: choice === value }} + style={[st.segment, choice === value && { backgroundColor: c.accent }]} + > + {label} + + ))} + + + {pushNote ?? + "Boxes tell this phone when an agent or a run needs you: which worktree and box, never what the agent wrote. They send it through Shipyard's push relay, which keeps nothing."} + + + + {boxes.map((b) => { + const d = data[b.id]; + const state = d?.error ? "Can't reach it" : d?.live ? "Live" : d?.info ? (d.info.version >= 2 ? "Connecting" : "Checking every few seconds (older berthd)") : "Connecting"; + return ( + + + + + {b.name} + + {d?.error ?? state} + + + {!demo && + + )) + )} + {apps.size > 0 && ntfyToo &&

ntfy is on too, so these phones may get each notification twice. Turn ntfy off below if they only use the app.

} + + ); +} diff --git a/docs/changelog.mdx b/docs/changelog.mdx index bd1f405d4..b68995f88 100644 --- a/docs/changelog.mdx +++ b/docs/changelog.mdx @@ -10,6 +10,12 @@ upgrades with `berth upgrade BOX`, or by running the again. ## Unreleased +- **Shipyard for iPhone.** A phone app that pairs with the same code as the + web phone app (Settings → Phone) and shows which agents need you across + your boxes: a session's conversation or its screen, its answers as + buttons, Stop, and a prompt to send; runs and their gates. It gets + notifications without ntfy, and Settings → Phone lists the phones that do, + to remove one. **Try the demo** works without a box. - **Worktrees fits a narrow window.** With the sidebar open on a small window, the table and its filters ran off the right edge. Now the Port column steps aside first and "vs base" after it (both are in a diff --git a/docs/guides/phone.mdx b/docs/guides/phone.mdx index b7c495819..93c8a44ff 100644 --- a/docs/guides/phone.mdx +++ b/docs/guides/phone.mdx @@ -27,6 +27,27 @@ the ntfy app. Boxes then push "Claude Code needs you · shop/checkout on devl" when an agent waits for you (and, if you switch it on, when one finishes its turn), and tapping it opens that agent in the phone app. +## The Shipyard app for iPhone + +The Shipyard app does what the web app does, and more: + +- **Pair** by scanning the same code in the app (Pair), or pasting its link. +- **Needs you** lists every paired box's agents, waiting first, and the runs + waiting at a gate. Boxes with an up-to-date berthd say what changes as it + happens; older ones are read every few seconds. +- **A session** shows its conversation (**Chat**) or its terminal (**Screen**), + the answers it offers as buttons (a permission reads as Allow, Always allow + or Deny), Enter, Stop, and a box for a prompt. +- **Runs** shows a run's gate, to approve, reject or pick an attempt, and its + steps. +- **Notifications** come without ntfy: in Boxes, choose Needs you (or Needs + you and done). Each box then notifies the phone through Shipyard's push + relay (below), and a notification opens its agent or run. Settings → Phone + on the laptop lists the phones that get them, and removes one. + +The app keeps each box's token in the iPhone's keychain, on that phone only. +**Try the demo** on its Pair screen shows made-up boxes, without one. + ## How it works Each box serves the phone app itself, on its tailnet address, port 1379.