mirror of
https://github.com/kennethnym/aris.git
synced 2026-04-15 14:21:17 +01:00
Compare commits
1 Commits
feat/pre-c
...
kn/combine
| Author | SHA1 | Date | |
|---|---|---|---|
|
7a37abca67
|
@@ -1 +0,0 @@
|
|||||||
bunx lint-staged
|
|
||||||
@@ -26,12 +26,6 @@ services:
|
|||||||
commands:
|
commands:
|
||||||
start: |
|
start: |
|
||||||
gitpod --context environment environment port open 3000 --name "Aelis Backend" --protocol http
|
gitpod --context environment environment port open 3000 --name "Aelis Backend" --protocol http
|
||||||
TS_IP=$(tailscale ip -4)
|
|
||||||
echo ""
|
|
||||||
echo "------------------ Bun Debugger ------------------"
|
|
||||||
echo "https://debug.bun.sh/#${TS_IP}:6499"
|
|
||||||
echo "------------------ Bun Debugger ------------------"
|
|
||||||
echo ""
|
|
||||||
cd apps/aelis-backend && bun run dev
|
cd apps/aelis-backend && bun run dev
|
||||||
|
|
||||||
admin-dashboard:
|
admin-dashboard:
|
||||||
|
|||||||
@@ -8,5 +8,5 @@
|
|||||||
"ignoreCase": true,
|
"ignoreCase": true,
|
||||||
"newlinesBetween": true
|
"newlinesBetween": true
|
||||||
},
|
},
|
||||||
"ignorePatterns": [".claude", ".ona", "drizzle", "fixtures"]
|
"ignorePatterns": [".claude", "fixtures"]
|
||||||
}
|
}
|
||||||
|
|||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"js/ts.experimental.useTsgo": true
|
|
||||||
}
|
|
||||||
7
apps/admin-dashboard/.prettierignore
Normal file
7
apps/admin-dashboard/.prettierignore
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
node_modules/
|
||||||
|
coverage/
|
||||||
|
.pnpm-store/
|
||||||
|
pnpm-lock.yaml
|
||||||
|
package-lock.json
|
||||||
|
pnpm-lock.yaml
|
||||||
|
yarn.lock
|
||||||
11
apps/admin-dashboard/.prettierrc
Normal file
11
apps/admin-dashboard/.prettierrc
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"endOfLine": "lf",
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": false,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"printWidth": 80,
|
||||||
|
"plugins": ["prettier-plugin-tailwindcss"],
|
||||||
|
"tailwindStylesheet": "src/index.css",
|
||||||
|
"tailwindFunctions": ["cn", "cva"]
|
||||||
|
}
|
||||||
23
apps/admin-dashboard/eslint.config.js
Normal file
23
apps/admin-dashboard/eslint.config.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import js from '@eslint/js'
|
||||||
|
import globals from 'globals'
|
||||||
|
import reactHooks from 'eslint-plugin-react-hooks'
|
||||||
|
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||||
|
import tseslint from 'typescript-eslint'
|
||||||
|
import { defineConfig, globalIgnores } from 'eslint/config'
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
globalIgnores(['dist']),
|
||||||
|
{
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
extends: [
|
||||||
|
js.configs.recommended,
|
||||||
|
tseslint.configs.recommended,
|
||||||
|
reactHooks.configs.flat.recommended,
|
||||||
|
reactRefresh.configs.vite,
|
||||||
|
],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
globals: globals.browser,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "admin-dashboard",
|
"name": "admin-dashboard",
|
||||||
"version": "0.0.1",
|
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build",
|
||||||
"lint": "oxlint .",
|
"lint": "eslint .",
|
||||||
"format": "oxfmt --write .",
|
"format": "prettier --write \"**/*.{ts,tsx}\"",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
@@ -30,11 +30,19 @@
|
|||||||
"tw-animate-css": "^1.4.0"
|
"tw-animate-css": "^1.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.39.1",
|
||||||
"@types/node": "^24.10.1",
|
"@types/node": "^24.10.1",
|
||||||
"@types/react": "^19.2.5",
|
"@types/react": "^19.2.5",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@vitejs/plugin-react": "^5.1.1",
|
"@vitejs/plugin-react": "^5.1.1",
|
||||||
"typescript": "^6",
|
"eslint": "^9.39.1",
|
||||||
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.24",
|
||||||
|
"globals": "^16.5.0",
|
||||||
|
"prettier": "^3.8.1",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.7.2",
|
||||||
|
"typescript": "~5.9.3",
|
||||||
|
"typescript-eslint": "^8.46.4",
|
||||||
"vite": "^7.2.4"
|
"vite": "^7.2.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useQueryClient, type QueryClient } from "@tanstack/react-query"
|
|
||||||
import { createRouter, RouterProvider } from "@tanstack/react-router"
|
import { createRouter, RouterProvider } from "@tanstack/react-router"
|
||||||
|
import { useQueryClient, type QueryClient } from "@tanstack/react-query"
|
||||||
|
|
||||||
import { routeTree } from "./route-tree.gen"
|
import { routeTree } from "./route-tree.gen"
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { useQuery } from "@tanstack/react-query"
|
import { useQuery } from "@tanstack/react-query"
|
||||||
import { Loader2, RefreshCw, TriangleAlert } from "lucide-react"
|
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
import { Loader2, RefreshCw, TriangleAlert } from "lucide-react"
|
||||||
|
|
||||||
import type { FeedItem } from "@/lib/api"
|
import type { FeedItem } from "@/lib/api"
|
||||||
|
import { fetchFeed } from "@/lib/api"
|
||||||
|
|
||||||
import { Badge } from "@/components/ui/badge"
|
import { Badge } from "@/components/ui/badge"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
import { fetchFeed } from "@/lib/api"
|
|
||||||
|
|
||||||
export function FeedPanel() {
|
export function FeedPanel() {
|
||||||
const {
|
const {
|
||||||
@@ -28,7 +28,9 @@ export function FeedPanel() {
|
|||||||
<div className="flex items-center justify-between gap-4">
|
<div className="flex items-center justify-between gap-4">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<h2 className="text-lg font-semibold tracking-tight">Feed</h2>
|
<h2 className="text-lg font-semibold tracking-tight">Feed</h2>
|
||||||
<p className="text-sm text-muted-foreground">Query the feed as the current user.</p>
|
<p className="text-sm text-muted-foreground">
|
||||||
|
Query the feed as the current user.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={() => refetch()} disabled={isFetching} size="sm">
|
<Button onClick={() => refetch()} disabled={isFetching} size="sm">
|
||||||
{isFetching ? (
|
{isFetching ? (
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { useQuery } from "@tanstack/react-query"
|
import { useQuery } from "@tanstack/react-query"
|
||||||
import { CircleCheck, CircleX, Loader2 } from "lucide-react"
|
import { CircleCheck, CircleX, Loader2 } from "lucide-react"
|
||||||
|
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
|
||||||
import { getServerUrl } from "@/lib/server-url"
|
import { getServerUrl } from "@/lib/server-url"
|
||||||
|
|
||||||
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
|
|
||||||
async function checkHealth(serverUrl: string): Promise<boolean> {
|
async function checkHealth(serverUrl: string): Promise<boolean> {
|
||||||
const res = await fetch(`${serverUrl}/health`)
|
const res = await fetch(`${serverUrl}/health`)
|
||||||
if (!res.ok) throw new Error(`HTTP ${res.status}`)
|
if (!res.ok) throw new Error(`HTTP ${res.status}`)
|
||||||
@@ -27,13 +28,17 @@ export function GeneralSettingsPanel() {
|
|||||||
<div className="mx-auto max-w-xl space-y-6">
|
<div className="mx-auto max-w-xl space-y-6">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<h2 className="text-lg font-semibold tracking-tight">General</h2>
|
<h2 className="text-lg font-semibold tracking-tight">General</h2>
|
||||||
<p className="text-sm text-muted-foreground">Backend server information.</p>
|
<p className="text-sm text-muted-foreground">
|
||||||
|
Backend server information.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Card className="-mx-4">
|
<Card className="-mx-4">
|
||||||
<CardHeader className="pb-4">
|
<CardHeader className="pb-4">
|
||||||
<CardTitle className="text-sm">Server</CardTitle>
|
<CardTitle className="text-sm">Server</CardTitle>
|
||||||
<CardDescription>Connected backend instance.</CardDescription>
|
<CardDescription>
|
||||||
|
Connected backend instance.
|
||||||
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="space-y-3 text-sm">
|
<div className="space-y-3 text-sm">
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import { useMutation } from "@tanstack/react-query"
|
import { useMutation } from "@tanstack/react-query"
|
||||||
import { Loader2, Settings2 } from "lucide-react"
|
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
import { Loader2, Settings2 } from "lucide-react"
|
||||||
import { toast } from "sonner"
|
import { toast } from "sonner"
|
||||||
|
|
||||||
import type { AuthSession } from "@/lib/auth"
|
import type { AuthSession } from "@/lib/auth"
|
||||||
|
import { signIn } from "@/lib/auth"
|
||||||
|
import { getServerUrl, setServerUrl } from "@/lib/server-url"
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/ui/input"
|
||||||
import { Label } from "@/components/ui/label"
|
import { Label } from "@/components/ui/label"
|
||||||
import { signIn } from "@/lib/auth"
|
|
||||||
import { getServerUrl, setServerUrl } from "@/lib/server-url"
|
|
||||||
|
|
||||||
interface LoginPageProps {
|
interface LoginPageProps {
|
||||||
onLogin: (session: AuthSession) => void
|
onLogin: (session: AuthSession) => void
|
||||||
@@ -86,10 +86,12 @@ export function LoginPage({ onLogin }: LoginPageProps) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<Button type="submit" className="w-full" disabled={loading}>
|
<Button type="submit" className="w-full" disabled={loading}>
|
||||||
{loading && <Loader2 className="size-4 animate-spin" />}
|
{loading && <Loader2 className="size-4 animate-spin" />}
|
||||||
{loading ? "Signing in…" : "Sign in"}
|
{loading ? "Signing in…" : "Sign in"}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
||||||
import { Info, Loader2, MapPin, Trash2 } from "lucide-react"
|
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
import { Info, Loader2, MapPin, Trash2 } from "lucide-react"
|
||||||
import { toast } from "sonner"
|
import { toast } from "sonner"
|
||||||
|
|
||||||
import type { ConfigFieldDef, SourceDefinition } from "@/lib/api"
|
import type { ConfigFieldDef, SourceDefinition } from "@/lib/api"
|
||||||
|
import { fetchSourceConfig, pushLocation, replaceSource, updateProviderConfig } from "@/lib/api"
|
||||||
|
|
||||||
import { Badge } from "@/components/ui/badge"
|
import { Badge } from "@/components/ui/badge"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
@@ -20,7 +21,6 @@ import {
|
|||||||
import { Separator } from "@/components/ui/separator"
|
import { Separator } from "@/components/ui/separator"
|
||||||
import { Switch } from "@/components/ui/switch"
|
import { Switch } from "@/components/ui/switch"
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||||
import { fetchSourceConfig, pushLocation, replaceSource, updateProviderConfig } from "@/lib/api"
|
|
||||||
|
|
||||||
interface SourceConfigPanelProps {
|
interface SourceConfigPanelProps {
|
||||||
source: SourceDefinition
|
source: SourceDefinition
|
||||||
@@ -74,24 +74,21 @@ export function SourceConfigPanel({ source, onUpdate }: SourceConfigPanelProps)
|
|||||||
|
|
||||||
const saveMutation = useMutation({
|
const saveMutation = useMutation({
|
||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
|
const promises: Promise<void>[] = [
|
||||||
|
replaceSource(source.id, { enabled, config: getUserConfig() }),
|
||||||
|
]
|
||||||
|
|
||||||
const credentialFields = getCredentialFields()
|
const credentialFields = getCredentialFields()
|
||||||
const hasCredentials = Object.values(credentialFields).some(
|
const hasCredentials = Object.values(credentialFields).some(
|
||||||
(v) => typeof v === "string" && v.length > 0,
|
(v) => typeof v === "string" && v.length > 0,
|
||||||
)
|
)
|
||||||
|
if (hasCredentials) {
|
||||||
|
promises.push(
|
||||||
|
updateProviderConfig(source.id, { credentials: credentialFields }),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const body: Parameters<typeof replaceSource>[1] = {
|
await Promise.all(promises)
|
||||||
enabled,
|
|
||||||
config: getUserConfig(),
|
|
||||||
}
|
|
||||||
if (hasCredentials && source.perUserCredentials) {
|
|
||||||
body.credentials = credentialFields
|
|
||||||
}
|
|
||||||
await replaceSource(source.id, body)
|
|
||||||
|
|
||||||
// For non-per-user credentials (provider-level), still use the admin endpoint.
|
|
||||||
if (hasCredentials && !source.perUserCredentials) {
|
|
||||||
await updateProviderConfig(source.id, { credentials: credentialFields })
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
setDirty({})
|
setDirty({})
|
||||||
@@ -160,6 +157,7 @@ export function SourceConfigPanel({ source, onUpdate }: SourceConfigPanelProps)
|
|||||||
) : (
|
) : (
|
||||||
<Badge variant="outline">Disabled</Badge>
|
<Badge variant="outline">Disabled</Badge>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-muted-foreground">{source.description}</p>
|
<p className="text-sm text-muted-foreground">{source.description}</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -309,9 +307,7 @@ function LocationCard() {
|
|||||||
<CardContent className="space-y-4">
|
<CardContent className="space-y-4">
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="loc-lat" className="text-xs font-medium">
|
<Label htmlFor="loc-lat" className="text-xs font-medium">Latitude</Label>
|
||||||
Latitude
|
|
||||||
</Label>
|
|
||||||
<Input
|
<Input
|
||||||
id="loc-lat"
|
id="loc-lat"
|
||||||
type="number"
|
type="number"
|
||||||
@@ -323,9 +319,7 @@ function LocationCard() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="loc-lng" className="text-xs font-medium">
|
<Label htmlFor="loc-lng" className="text-xs font-medium">Longitude</Label>
|
||||||
Longitude
|
|
||||||
</Label>
|
|
||||||
<Input
|
<Input
|
||||||
id="loc-lng"
|
id="loc-lng"
|
||||||
type="number"
|
type="number"
|
||||||
@@ -414,38 +408,6 @@ function FieldInput({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field.type === "multiselect" && field.options) {
|
|
||||||
const selected = Array.isArray(value) ? (value as string[]) : []
|
|
||||||
|
|
||||||
function toggle(optValue: string) {
|
|
||||||
const next = selected.includes(optValue)
|
|
||||||
? selected.filter((v) => v !== optValue)
|
|
||||||
: [...selected, optValue]
|
|
||||||
onChange(next)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Label className="text-xs font-medium">{labelContent}</Label>
|
|
||||||
<div className="flex flex-wrap gap-1.5">
|
|
||||||
{field.options!.map((opt) => {
|
|
||||||
const isSelected = selected.includes(opt.value)
|
|
||||||
return (
|
|
||||||
<Badge
|
|
||||||
key={opt.value}
|
|
||||||
variant={isSelected ? "default" : "outline"}
|
|
||||||
className={`cursor-pointer select-none ${isSelected ? "" : "opacity-60 hover:opacity-100"}`}
|
|
||||||
onClick={() => !disabled && toggle(opt.value)}
|
|
||||||
>
|
|
||||||
{opt.label}
|
|
||||||
</Badge>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (field.type === "number") {
|
if (field.type === "number") {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@@ -494,8 +456,6 @@ function buildInitialValues(
|
|||||||
values[name] = saved[name]
|
values[name] = saved[name]
|
||||||
} else if (field.defaultValue !== undefined) {
|
} else if (field.defaultValue !== undefined) {
|
||||||
values[name] = field.defaultValue
|
values[name] = field.defaultValue
|
||||||
} else if (field.type === "multiselect") {
|
|
||||||
values[name] = []
|
|
||||||
} else {
|
} else {
|
||||||
values[name] = field.type === "number" ? undefined : ""
|
values[name] = field.type === "number" ? undefined : ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ type ThemeProviderState = {
|
|||||||
const COLOR_SCHEME_QUERY = "(prefers-color-scheme: dark)"
|
const COLOR_SCHEME_QUERY = "(prefers-color-scheme: dark)"
|
||||||
const THEME_VALUES: Theme[] = ["dark", "light", "system"]
|
const THEME_VALUES: Theme[] = ["dark", "light", "system"]
|
||||||
|
|
||||||
const ThemeProviderContext = React.createContext<ThemeProviderState | undefined>(undefined)
|
const ThemeProviderContext = React.createContext<
|
||||||
|
ThemeProviderState | undefined
|
||||||
|
>(undefined)
|
||||||
|
|
||||||
function isTheme(value: string | null): value is Theme {
|
function isTheme(value: string | null): value is Theme {
|
||||||
if (value === null) {
|
if (value === null) {
|
||||||
@@ -41,8 +43,8 @@ function disableTransitionsTemporarily() {
|
|||||||
const style = document.createElement("style")
|
const style = document.createElement("style")
|
||||||
style.appendChild(
|
style.appendChild(
|
||||||
document.createTextNode(
|
document.createTextNode(
|
||||||
"*,*::before,*::after{-webkit-transition:none!important;transition:none!important}",
|
"*,*::before,*::after{-webkit-transition:none!important;transition:none!important}"
|
||||||
),
|
)
|
||||||
)
|
)
|
||||||
document.head.appendChild(style)
|
document.head.appendChild(style)
|
||||||
|
|
||||||
@@ -65,7 +67,9 @@ function isEditableTarget(target: EventTarget | null) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
const editableParent = target.closest("input, textarea, select, [contenteditable='true']")
|
const editableParent = target.closest(
|
||||||
|
"input, textarea, select, [contenteditable='true']"
|
||||||
|
)
|
||||||
if (editableParent) {
|
if (editableParent) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -94,14 +98,17 @@ export function ThemeProvider({
|
|||||||
localStorage.setItem(storageKey, nextTheme)
|
localStorage.setItem(storageKey, nextTheme)
|
||||||
setThemeState(nextTheme)
|
setThemeState(nextTheme)
|
||||||
},
|
},
|
||||||
[storageKey],
|
[storageKey]
|
||||||
)
|
)
|
||||||
|
|
||||||
const applyTheme = React.useCallback(
|
const applyTheme = React.useCallback(
|
||||||
(nextTheme: Theme) => {
|
(nextTheme: Theme) => {
|
||||||
const root = document.documentElement
|
const root = document.documentElement
|
||||||
const resolvedTheme = nextTheme === "system" ? getSystemTheme() : nextTheme
|
const resolvedTheme =
|
||||||
const restoreTransitions = disableTransitionOnChange ? disableTransitionsTemporarily() : null
|
nextTheme === "system" ? getSystemTheme() : nextTheme
|
||||||
|
const restoreTransitions = disableTransitionOnChange
|
||||||
|
? disableTransitionsTemporarily()
|
||||||
|
: null
|
||||||
|
|
||||||
root.classList.remove("light", "dark")
|
root.classList.remove("light", "dark")
|
||||||
root.classList.add(resolvedTheme)
|
root.classList.add(resolvedTheme)
|
||||||
@@ -110,7 +117,7 @@ export function ThemeProvider({
|
|||||||
restoreTransitions()
|
restoreTransitions()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[disableTransitionOnChange],
|
[disableTransitionOnChange]
|
||||||
)
|
)
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@@ -202,7 +209,7 @@ export function ThemeProvider({
|
|||||||
theme,
|
theme,
|
||||||
setTheme,
|
setTheme,
|
||||||
}),
|
}),
|
||||||
[theme, setTheme],
|
[theme, setTheme]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
|
||||||
import { Accordion as AccordionPrimitive } from "radix-ui"
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import { Accordion as AccordionPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
||||||
|
|
||||||
function Accordion({ className, ...props }: React.ComponentProps<typeof AccordionPrimitive.Root>) {
|
function Accordion({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof AccordionPrimitive.Root>) {
|
||||||
return (
|
return (
|
||||||
<AccordionPrimitive.Root
|
<AccordionPrimitive.Root
|
||||||
data-slot="accordion"
|
data-slot="accordion"
|
||||||
className={cn("flex w-full flex-col overflow-hidden rounded-md border", className)}
|
className={cn(
|
||||||
|
"flex w-full flex-col overflow-hidden rounded-md border",
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@@ -40,19 +46,13 @@ function AccordionTrigger({
|
|||||||
data-slot="accordion-trigger"
|
data-slot="accordion-trigger"
|
||||||
className={cn(
|
className={cn(
|
||||||
"group/accordion-trigger relative flex flex-1 items-start justify-between gap-6 border border-transparent p-2 text-left text-xs/relaxed font-medium transition-all outline-none hover:underline disabled:pointer-events-none disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground",
|
"group/accordion-trigger relative flex flex-1 items-start justify-between gap-6 border border-transparent p-2 text-left text-xs/relaxed font-medium transition-all outline-none hover:underline disabled:pointer-events-none disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
<ChevronDownIcon
|
<ChevronDownIcon data-slot="accordion-trigger-icon" className="pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden" />
|
||||||
data-slot="accordion-trigger-icon"
|
<ChevronUpIcon data-slot="accordion-trigger-icon" className="pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline" />
|
||||||
className="pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden"
|
|
||||||
/>
|
|
||||||
<ChevronUpIcon
|
|
||||||
data-slot="accordion-trigger-icon"
|
|
||||||
className="pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline"
|
|
||||||
/>
|
|
||||||
</AccordionPrimitive.Trigger>
|
</AccordionPrimitive.Trigger>
|
||||||
</AccordionPrimitive.Header>
|
</AccordionPrimitive.Header>
|
||||||
)
|
)
|
||||||
@@ -72,7 +72,7 @@ function AccordionContent({
|
|||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-(--radix-accordion-content-height) pt-0 pb-4 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
|
"h-(--radix-accordion-content-height) pt-0 pb-4 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { cva, type VariantProps } from "class-variance-authority"
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import { cva, type VariantProps } from "class-variance-authority"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ const alertVariants = cva(
|
|||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "default",
|
variant: "default",
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
function Alert({
|
function Alert({
|
||||||
@@ -40,20 +40,23 @@ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
data-slot="alert-title"
|
data-slot="alert-title"
|
||||||
className={cn(
|
className={cn(
|
||||||
"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground",
|
"font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function AlertDescription({ className, ...props }: React.ComponentProps<"div">) {
|
function AlertDescription({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<"div">) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="alert-description"
|
data-slot="alert-description"
|
||||||
className={cn(
|
className={cn(
|
||||||
"text-xs/relaxed text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
|
"text-xs/relaxed text-balance text-muted-foreground md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import * as React from "react"
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
import { cva, type VariantProps } from "class-variance-authority"
|
||||||
import { Slot } from "radix-ui"
|
import { Slot } from "radix-ui"
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
@@ -10,19 +10,21 @@ const badgeVariants = cva(
|
|||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
||||||
secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
|
secondary:
|
||||||
|
"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
|
||||||
destructive:
|
destructive:
|
||||||
"bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
|
"bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
|
||||||
outline:
|
outline:
|
||||||
"border-border bg-input/20 text-foreground dark:bg-input/30 [a]:hover:bg-muted [a]:hover:text-muted-foreground",
|
"border-border bg-input/20 text-foreground dark:bg-input/30 [a]:hover:bg-muted [a]:hover:text-muted-foreground",
|
||||||
ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
|
ghost:
|
||||||
|
"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
|
||||||
link: "text-primary underline-offset-4 hover:underline",
|
link: "text-primary underline-offset-4 hover:underline",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: "default",
|
variant: "default",
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
function Badge({
|
function Badge({
|
||||||
@@ -30,7 +32,8 @@ function Badge({
|
|||||||
variant = "default",
|
variant = "default",
|
||||||
asChild = false,
|
asChild = false,
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
|
}: React.ComponentProps<"span"> &
|
||||||
|
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
|
||||||
const Comp = asChild ? Slot.Root : "span"
|
const Comp = asChild ? Slot.Root : "span"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import * as React from "react"
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
import { cva, type VariantProps } from "class-variance-authority"
|
||||||
import { Slot } from "radix-ui"
|
import { Slot } from "radix-ui"
|
||||||
import * as React from "react"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ const buttonVariants = cva(
|
|||||||
variant: "default",
|
variant: "default",
|
||||||
size: "default",
|
size: "default",
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
function Button({
|
function Button({
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ function Card({
|
|||||||
data-size={size}
|
data-size={size}
|
||||||
className={cn(
|
className={cn(
|
||||||
"group/card flex flex-col gap-4 overflow-hidden rounded-lg bg-card py-4 text-xs/relaxed text-card-foreground ring-1 ring-foreground/10 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg",
|
"group/card flex flex-col gap-4 overflow-hidden rounded-lg bg-card py-4 text-xs/relaxed text-card-foreground ring-1 ring-foreground/10 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
@@ -26,7 +26,7 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
data-slot="card-header"
|
data-slot="card-header"
|
||||||
className={cn(
|
className={cn(
|
||||||
"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-lg px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3",
|
"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-lg px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
@@ -34,7 +34,13 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
return <div data-slot="card-title" className={cn("text-sm font-medium", className)} {...props} />
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="card-title"
|
||||||
|
className={cn("text-sm font-medium", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
@@ -51,7 +57,10 @@ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="card-action"
|
data-slot="card-action"
|
||||||
className={cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className)}
|
className={cn(
|
||||||
|
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@@ -73,11 +82,19 @@ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
data-slot="card-footer"
|
data-slot="card-footer"
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center rounded-b-lg px-4 group-data-[size=sm]/card:px-3 [.border-t]:pt-4 group-data-[size=sm]/card:[.border-t]:pt-3",
|
"flex items-center rounded-b-lg px-4 group-data-[size=sm]/card:px-3 [.border-t]:pt-4 group-data-[size=sm]/card:[.border-t]:pt-3",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent }
|
export {
|
||||||
|
Card,
|
||||||
|
CardHeader,
|
||||||
|
CardFooter,
|
||||||
|
CardTitle,
|
||||||
|
CardAction,
|
||||||
|
CardDescription,
|
||||||
|
CardContent,
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,20 +2,32 @@
|
|||||||
|
|
||||||
import { Collapsible as CollapsiblePrimitive } from "radix-ui"
|
import { Collapsible as CollapsiblePrimitive } from "radix-ui"
|
||||||
|
|
||||||
function Collapsible({ ...props }: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {
|
function Collapsible({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {
|
||||||
return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
|
return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
function CollapsibleTrigger({
|
function CollapsibleTrigger({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {
|
}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {
|
||||||
return <CollapsiblePrimitive.CollapsibleTrigger data-slot="collapsible-trigger" {...props} />
|
return (
|
||||||
|
<CollapsiblePrimitive.CollapsibleTrigger
|
||||||
|
data-slot="collapsible-trigger"
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function CollapsibleContent({
|
function CollapsibleContent({
|
||||||
...props
|
...props
|
||||||
}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {
|
}: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {
|
||||||
return <CollapsiblePrimitive.CollapsibleContent data-slot="collapsible-content" {...props} />
|
return (
|
||||||
|
<CollapsiblePrimitive.CollapsibleContent
|
||||||
|
data-slot="collapsible-content"
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Collapsible, CollapsibleTrigger, CollapsibleContent }
|
export { Collapsible, CollapsibleTrigger, CollapsibleContent }
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
|||||||
data-slot="input"
|
data-slot="input"
|
||||||
className={cn(
|
className={cn(
|
||||||
"h-7 w-full min-w-0 rounded-md border border-input bg-input/20 px-2 py-0.5 text-sm transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-xs/relaxed file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 md:text-xs/relaxed dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
"h-7 w-full min-w-0 rounded-md border border-input bg-input/20 px-2 py-0.5 text-sm transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-xs/relaxed file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 md:text-xs/relaxed dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
import { Label as LabelPrimitive } from "radix-ui"
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import { Label as LabelPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
function Label({ className, ...props }: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
function Label({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
||||||
return (
|
return (
|
||||||
<LabelPrimitive.Root
|
<LabelPrimitive.Root
|
||||||
data-slot="label"
|
data-slot="label"
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex items-center gap-2 text-xs/relaxed leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
"flex items-center gap-2 text-xs/relaxed leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react"
|
|
||||||
import { Select as SelectPrimitive } from "radix-ui"
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import { Select as SelectPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react"
|
||||||
|
|
||||||
function Select({ ...props }: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
function Select({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
||||||
return <SelectPrimitive.Root data-slot="select" {...props} />
|
return <SelectPrimitive.Root data-slot="select" {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectGroup({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Group>) {
|
function SelectGroup({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Group>) {
|
||||||
return (
|
return (
|
||||||
<SelectPrimitive.Group
|
<SelectPrimitive.Group
|
||||||
data-slot="select-group"
|
data-slot="select-group"
|
||||||
@@ -18,7 +23,9 @@ function SelectGroup({ className, ...props }: React.ComponentProps<typeof Select
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectValue({ ...props }: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
function SelectValue({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
||||||
return <SelectPrimitive.Value data-slot="select-value" {...props} />
|
return <SelectPrimitive.Value data-slot="select-value" {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +43,7 @@ function SelectTrigger({
|
|||||||
data-size={size}
|
data-size={size}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-fit items-center justify-between gap-1.5 rounded-md border border-input bg-input/20 px-2 py-1.5 text-xs/relaxed whitespace-nowrap transition-colors outline-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-7 data-[size=sm]:h-6 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
|
"flex w-fit items-center justify-between gap-1.5 rounded-md border border-input bg-input/20 px-2 py-1.5 text-xs/relaxed whitespace-nowrap transition-colors outline-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-7 data-[size=sm]:h-6 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
@@ -60,12 +67,7 @@ function SelectContent({
|
|||||||
<SelectPrimitive.Content
|
<SelectPrimitive.Content
|
||||||
data-slot="select-content"
|
data-slot="select-content"
|
||||||
data-align-trigger={position === "item-aligned"}
|
data-align-trigger={position === "item-aligned"}
|
||||||
className={cn(
|
className={cn("relative z-50 max-h-(--radix-select-content-available-height) min-w-32 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", position ==="popper"&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className )}
|
||||||
"relative z-50 max-h-(--radix-select-content-available-height) min-w-32 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
||||||
position === "popper" &&
|
|
||||||
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
position={position}
|
position={position}
|
||||||
align={align}
|
align={align}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -75,7 +77,7 @@ function SelectContent({
|
|||||||
data-position={position}
|
data-position={position}
|
||||||
className={cn(
|
className={cn(
|
||||||
"data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)",
|
"data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)",
|
||||||
position === "popper" && "",
|
position === "popper" && ""
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
@@ -86,7 +88,10 @@ function SelectContent({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectLabel({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Label>) {
|
function SelectLabel({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SelectPrimitive.Label>) {
|
||||||
return (
|
return (
|
||||||
<SelectPrimitive.Label
|
<SelectPrimitive.Label
|
||||||
data-slot="select-label"
|
data-slot="select-label"
|
||||||
@@ -106,7 +111,7 @@ function SelectItem({
|
|||||||
data-slot="select-item"
|
data-slot="select-item"
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex min-h-7 w-full cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs/relaxed outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
"relative flex min-h-7 w-full cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs/relaxed outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
@@ -127,7 +132,10 @@ function SelectSeparator({
|
|||||||
return (
|
return (
|
||||||
<SelectPrimitive.Separator
|
<SelectPrimitive.Separator
|
||||||
data-slot="select-separator"
|
data-slot="select-separator"
|
||||||
className={cn("pointer-events-none -mx-1 my-1 h-px bg-border/50", className)}
|
className={cn(
|
||||||
|
"pointer-events-none -mx-1 my-1 h-px bg-border/50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@@ -142,11 +150,12 @@ function SelectScrollUpButton({
|
|||||||
data-slot="select-scroll-up-button"
|
data-slot="select-scroll-up-button"
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-3.5",
|
"z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-3.5",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ChevronUpIcon />
|
<ChevronUpIcon
|
||||||
|
/>
|
||||||
</SelectPrimitive.ScrollUpButton>
|
</SelectPrimitive.ScrollUpButton>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -160,11 +169,12 @@ function SelectScrollDownButton({
|
|||||||
data-slot="select-scroll-down-button"
|
data-slot="select-scroll-down-button"
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-3.5",
|
"z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-3.5",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<ChevronDownIcon />
|
<ChevronDownIcon
|
||||||
|
/>
|
||||||
</SelectPrimitive.ScrollDownButton>
|
</SelectPrimitive.ScrollDownButton>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Separator as SeparatorPrimitive } from "radix-ui"
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import { Separator as SeparatorPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ function Separator({
|
|||||||
orientation={orientation}
|
orientation={orientation}
|
||||||
className={cn(
|
className={cn(
|
||||||
"shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
|
"shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,23 +1,29 @@
|
|||||||
import { XIcon } from "lucide-react"
|
|
||||||
import { Dialog as SheetPrimitive } from "radix-ui"
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import { Dialog as SheetPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button"
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { XIcon } from "lucide-react"
|
||||||
|
|
||||||
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
|
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
|
||||||
return <SheetPrimitive.Root data-slot="sheet" {...props} />
|
return <SheetPrimitive.Root data-slot="sheet" {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
function SheetTrigger({ ...props }: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
|
function SheetTrigger({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
|
||||||
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
|
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
function SheetClose({ ...props }: React.ComponentProps<typeof SheetPrimitive.Close>) {
|
function SheetClose({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SheetPrimitive.Close>) {
|
||||||
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
|
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
function SheetPortal({ ...props }: React.ComponentProps<typeof SheetPrimitive.Portal>) {
|
function SheetPortal({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SheetPrimitive.Portal>) {
|
||||||
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
|
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +36,7 @@ function SheetOverlay({
|
|||||||
data-slot="sheet-overlay"
|
data-slot="sheet-overlay"
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed inset-0 z-50 bg-black/80 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
|
"fixed inset-0 z-50 bg-black/80 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
@@ -55,15 +61,20 @@ function SheetContent({
|
|||||||
data-side={side}
|
data-side={side}
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed z-50 flex flex-col bg-background bg-clip-padding text-xs/relaxed shadow-lg transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-[side=bottom]:data-open:slide-in-from-bottom-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:animate-out data-closed:fade-out-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=right]:data-closed:slide-out-to-right-10 data-[side=top]:data-closed:slide-out-to-top-10",
|
"fixed z-50 flex flex-col bg-background bg-clip-padding text-xs/relaxed shadow-lg transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-[side=bottom]:data-open:slide-in-from-bottom-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:animate-out data-closed:fade-out-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=right]:data-closed:slide-out-to-right-10 data-[side=top]:data-closed:slide-out-to-top-10",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
{showCloseButton && (
|
{showCloseButton && (
|
||||||
<SheetPrimitive.Close data-slot="sheet-close" asChild>
|
<SheetPrimitive.Close data-slot="sheet-close" asChild>
|
||||||
<Button variant="ghost" className="absolute top-4 right-4" size="icon-sm">
|
<Button
|
||||||
<XIcon />
|
variant="ghost"
|
||||||
|
className="absolute top-4 right-4"
|
||||||
|
size="icon-sm"
|
||||||
|
>
|
||||||
|
<XIcon
|
||||||
|
/>
|
||||||
<span className="sr-only">Close</span>
|
<span className="sr-only">Close</span>
|
||||||
</Button>
|
</Button>
|
||||||
</SheetPrimitive.Close>
|
</SheetPrimitive.Close>
|
||||||
@@ -93,7 +104,10 @@ function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SheetTitle({ className, ...props }: React.ComponentProps<typeof SheetPrimitive.Title>) {
|
function SheetTitle({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SheetPrimitive.Title>) {
|
||||||
return (
|
return (
|
||||||
<SheetPrimitive.Title
|
<SheetPrimitive.Title
|
||||||
data-slot="sheet-title"
|
data-slot="sheet-title"
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { cva, type VariantProps } from "class-variance-authority"
|
|
||||||
import { PanelLeftIcon } from "lucide-react"
|
|
||||||
import { Slot } from "radix-ui"
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import { cva, type VariantProps } from "class-variance-authority"
|
||||||
|
import { Slot } from "radix-ui"
|
||||||
|
|
||||||
|
import { useIsMobile } from "@/hooks/use-mobile"
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/ui/input"
|
||||||
import { Separator } from "@/components/ui/separator"
|
import { Separator } from "@/components/ui/separator"
|
||||||
@@ -16,9 +17,12 @@ import {
|
|||||||
SheetTitle,
|
SheetTitle,
|
||||||
} from "@/components/ui/sheet"
|
} from "@/components/ui/sheet"
|
||||||
import { Skeleton } from "@/components/ui/skeleton"
|
import { Skeleton } from "@/components/ui/skeleton"
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
import {
|
||||||
import { useIsMobile } from "@/hooks/use-mobile"
|
Tooltip,
|
||||||
import { cn } from "@/lib/utils"
|
TooltipContent,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@/components/ui/tooltip"
|
||||||
|
import { PanelLeftIcon } from "lucide-react"
|
||||||
|
|
||||||
const SIDEBAR_COOKIE_NAME = "sidebar_state"
|
const SIDEBAR_COOKIE_NAME = "sidebar_state"
|
||||||
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
|
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
|
||||||
@@ -80,7 +84,7 @@ function SidebarProvider({
|
|||||||
// This sets the cookie to keep the sidebar state.
|
// This sets the cookie to keep the sidebar state.
|
||||||
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
|
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
|
||||||
},
|
},
|
||||||
[setOpenProp, open],
|
[setOpenProp, open]
|
||||||
)
|
)
|
||||||
|
|
||||||
// Helper to toggle the sidebar.
|
// Helper to toggle the sidebar.
|
||||||
@@ -91,7 +95,10 @@ function SidebarProvider({
|
|||||||
// Adds a keyboard shortcut to toggle the sidebar.
|
// Adds a keyboard shortcut to toggle the sidebar.
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
if (
|
||||||
|
event.key === SIDEBAR_KEYBOARD_SHORTCUT &&
|
||||||
|
(event.metaKey || event.ctrlKey)
|
||||||
|
) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
toggleSidebar()
|
toggleSidebar()
|
||||||
}
|
}
|
||||||
@@ -115,7 +122,7 @@ function SidebarProvider({
|
|||||||
setOpenMobile,
|
setOpenMobile,
|
||||||
toggleSidebar,
|
toggleSidebar,
|
||||||
}),
|
}),
|
||||||
[state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar],
|
[state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -131,7 +138,7 @@ function SidebarProvider({
|
|||||||
}
|
}
|
||||||
className={cn(
|
className={cn(
|
||||||
"group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar",
|
"group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
@@ -162,7 +169,7 @@ function Sidebar({
|
|||||||
data-slot="sidebar"
|
data-slot="sidebar"
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground",
|
"flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
@@ -215,7 +222,7 @@ function Sidebar({
|
|||||||
"group-data-[side=right]:rotate-180",
|
"group-data-[side=right]:rotate-180",
|
||||||
variant === "floating" || variant === "inset"
|
variant === "floating" || variant === "inset"
|
||||||
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"
|
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"
|
||||||
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon)",
|
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
@@ -227,7 +234,7 @@ function Sidebar({
|
|||||||
variant === "floating" || variant === "inset"
|
variant === "floating" || variant === "inset"
|
||||||
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
|
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
|
||||||
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
|
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
@@ -243,7 +250,11 @@ function Sidebar({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<typeof Button>) {
|
function SidebarTrigger({
|
||||||
|
className,
|
||||||
|
onClick,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof Button>) {
|
||||||
const { toggleSidebar } = useSidebar()
|
const { toggleSidebar } = useSidebar()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -283,7 +294,7 @@ function SidebarRail({ className, ...props }: React.ComponentProps<"button">) {
|
|||||||
"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar",
|
"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar",
|
||||||
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
|
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
|
||||||
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
|
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
@@ -296,19 +307,25 @@ function SidebarInset({ className, ...props }: React.ComponentProps<"main">) {
|
|||||||
data-slot="sidebar-inset"
|
data-slot="sidebar-inset"
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex w-full flex-1 flex-col bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2",
|
"relative flex w-full flex-1 flex-col bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarInput({ className, ...props }: React.ComponentProps<typeof Input>) {
|
function SidebarInput({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof Input>) {
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
data-slot="sidebar-input"
|
data-slot="sidebar-input"
|
||||||
data-sidebar="input"
|
data-sidebar="input"
|
||||||
className={cn("h-8 w-full border-input bg-muted/20 dark:bg-muted/30", className)}
|
className={cn(
|
||||||
|
"h-8 w-full border-input bg-muted/20 dark:bg-muted/30",
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@@ -336,7 +353,10 @@ function SidebarFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarSeparator({ className, ...props }: React.ComponentProps<typeof Separator>) {
|
function SidebarSeparator({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof Separator>) {
|
||||||
return (
|
return (
|
||||||
<Separator
|
<Separator
|
||||||
data-slot="sidebar-separator"
|
data-slot="sidebar-separator"
|
||||||
@@ -354,7 +374,7 @@ function SidebarContent({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
data-sidebar="content"
|
data-sidebar="content"
|
||||||
className={cn(
|
className={cn(
|
||||||
"no-scrollbar flex min-h-0 flex-1 flex-col gap-0 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
|
"no-scrollbar flex min-h-0 flex-1 flex-col gap-0 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
@@ -366,7 +386,10 @@ function SidebarGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|||||||
<div
|
<div
|
||||||
data-slot="sidebar-group"
|
data-slot="sidebar-group"
|
||||||
data-sidebar="group"
|
data-sidebar="group"
|
||||||
className={cn("relative flex w-full min-w-0 flex-col px-2 py-1", className)}
|
className={cn(
|
||||||
|
"relative flex w-full min-w-0 flex-col px-2 py-1",
|
||||||
|
className
|
||||||
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@@ -385,7 +408,7 @@ function SidebarGroupLabel({
|
|||||||
data-sidebar="group-label"
|
data-sidebar="group-label"
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-8 shrink-0 items-center rounded-md px-2 text-xs text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
"flex h-8 shrink-0 items-center rounded-md px-2 text-xs text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
@@ -405,14 +428,17 @@ function SidebarGroupAction({
|
|||||||
data-sidebar="group-action"
|
data-sidebar="group-action"
|
||||||
className={cn(
|
className={cn(
|
||||||
"absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
|
"absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarGroupContent({ className, ...props }: React.ComponentProps<"div">) {
|
function SidebarGroupContent({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<"div">) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="sidebar-group-content"
|
data-slot="sidebar-group-content"
|
||||||
@@ -464,7 +490,7 @@ const sidebarMenuButtonVariants = cva(
|
|||||||
variant: "default",
|
variant: "default",
|
||||||
size: "default",
|
size: "default",
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
function SidebarMenuButton({
|
function SidebarMenuButton({
|
||||||
@@ -536,21 +562,24 @@ function SidebarMenuAction({
|
|||||||
"absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-[calc(var(--radius-sm)-2px)] p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
|
"absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-[calc(var(--radius-sm)-2px)] p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
|
||||||
showOnHover &&
|
showOnHover &&
|
||||||
"group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-data-active/menu-button:text-sidebar-accent-foreground aria-expanded:opacity-100 md:opacity-0",
|
"group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-data-active/menu-button:text-sidebar-accent-foreground aria-expanded:opacity-100 md:opacity-0",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarMenuBadge({ className, ...props }: React.ComponentProps<"div">) {
|
function SidebarMenuBadge({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<"div">) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-slot="sidebar-menu-badge"
|
data-slot="sidebar-menu-badge"
|
||||||
data-sidebar="menu-badge"
|
data-sidebar="menu-badge"
|
||||||
className={cn(
|
className={cn(
|
||||||
"pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-[calc(var(--radius-sm)-2px)] px-1 text-xs font-medium text-sidebar-foreground tabular-nums select-none group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 peer-data-active/menu-button:text-sidebar-accent-foreground",
|
"pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-[calc(var(--radius-sm)-2px)] px-1 text-xs font-medium text-sidebar-foreground tabular-nums select-none group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 peer-data-active/menu-button:text-sidebar-accent-foreground",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
@@ -576,7 +605,12 @@ function SidebarMenuSkeleton({
|
|||||||
className={cn("flex h-8 items-center gap-2 rounded-md px-2", className)}
|
className={cn("flex h-8 items-center gap-2 rounded-md px-2", className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{showIcon && <Skeleton className="size-4 rounded-md" data-sidebar="menu-skeleton-icon" />}
|
{showIcon && (
|
||||||
|
<Skeleton
|
||||||
|
className="size-4 rounded-md"
|
||||||
|
data-sidebar="menu-skeleton-icon"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Skeleton
|
<Skeleton
|
||||||
className="h-4 max-w-(--skeleton-width) flex-1"
|
className="h-4 max-w-(--skeleton-width) flex-1"
|
||||||
data-sidebar="menu-skeleton-text"
|
data-sidebar="menu-skeleton-text"
|
||||||
@@ -597,14 +631,17 @@ function SidebarMenuSub({ className, ...props }: React.ComponentProps<"ul">) {
|
|||||||
data-sidebar="menu-sub"
|
data-sidebar="menu-sub"
|
||||||
className={cn(
|
className={cn(
|
||||||
"mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5 group-data-[collapsible=icon]:hidden",
|
"mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5 group-data-[collapsible=icon]:hidden",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function SidebarMenuSubItem({ className, ...props }: React.ComponentProps<"li">) {
|
function SidebarMenuSubItem({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<"li">) {
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
data-slot="sidebar-menu-sub-item"
|
data-slot="sidebar-menu-sub-item"
|
||||||
@@ -636,7 +673,7 @@ function SidebarMenuSubButton({
|
|||||||
data-active={isActive}
|
data-active={isActive}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden group-data-[collapsible=icon]:hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[size=md]:text-xs data-[size=sm]:text-xs data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
|
"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden group-data-[collapsible=icon]:hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[size=md]:text-xs data-[size=sm]:text-xs data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,15 +1,8 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import {
|
|
||||||
CircleCheckIcon,
|
|
||||||
InfoIcon,
|
|
||||||
TriangleAlertIcon,
|
|
||||||
OctagonXIcon,
|
|
||||||
Loader2Icon,
|
|
||||||
} from "lucide-react"
|
|
||||||
import { Toaster as Sonner, type ToasterProps } from "sonner"
|
|
||||||
|
|
||||||
import { useTheme } from "@/components/theme-provider"
|
import { useTheme } from "@/components/theme-provider"
|
||||||
|
import { Toaster as Sonner, type ToasterProps } from "sonner"
|
||||||
|
import { CircleCheckIcon, InfoIcon, TriangleAlertIcon, OctagonXIcon, Loader2Icon } from "lucide-react"
|
||||||
|
|
||||||
const Toaster = ({ ...props }: ToasterProps) => {
|
const Toaster = ({ ...props }: ToasterProps) => {
|
||||||
const { theme = "system" } = useTheme()
|
const { theme = "system" } = useTheme()
|
||||||
@@ -19,11 +12,21 @@ const Toaster = ({ ...props }: ToasterProps) => {
|
|||||||
theme={theme as ToasterProps["theme"]}
|
theme={theme as ToasterProps["theme"]}
|
||||||
className="toaster group"
|
className="toaster group"
|
||||||
icons={{
|
icons={{
|
||||||
success: <CircleCheckIcon className="size-4" />,
|
success: (
|
||||||
info: <InfoIcon className="size-4" />,
|
<CircleCheckIcon className="size-4" />
|
||||||
warning: <TriangleAlertIcon className="size-4" />,
|
),
|
||||||
error: <OctagonXIcon className="size-4" />,
|
info: (
|
||||||
loading: <Loader2Icon className="size-4 animate-spin" />,
|
<InfoIcon className="size-4" />
|
||||||
|
),
|
||||||
|
warning: (
|
||||||
|
<TriangleAlertIcon className="size-4" />
|
||||||
|
),
|
||||||
|
error: (
|
||||||
|
<OctagonXIcon className="size-4" />
|
||||||
|
),
|
||||||
|
loading: (
|
||||||
|
<Loader2Icon className="size-4 animate-spin" />
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
style={
|
style={
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { Switch as SwitchPrimitive } from "radix-ui"
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import { Switch as SwitchPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ function Switch({
|
|||||||
data-size={size}
|
data-size={size}
|
||||||
className={cn(
|
className={cn(
|
||||||
"peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 data-[size=default]:h-[16.6px] data-[size=default]:w-[28px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50",
|
"peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 data-[size=default]:h-[16.6px] data-[size=default]:w-[28px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { Tooltip as TooltipPrimitive } from "radix-ui"
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import { Tooltip as TooltipPrimitive } from "radix-ui"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
@@ -18,11 +18,15 @@ function TooltipProvider({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function Tooltip({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
|
function Tooltip({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
|
||||||
return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
return <TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
function TooltipTrigger({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
function TooltipTrigger({
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
||||||
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
|
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +43,7 @@ function TooltipContent({
|
|||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
"z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
||||||
className,
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -75,7 +75,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
--font-sans: "Inter Variable", sans-serif;
|
--font-sans: 'Inter Variable', sans-serif;
|
||||||
--color-sidebar-ring: var(--sidebar-ring);
|
--color-sidebar-ring: var(--sidebar-ring);
|
||||||
--color-sidebar-border: var(--sidebar-border);
|
--color-sidebar-border: var(--sidebar-border);
|
||||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ function serverBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ConfigFieldDef {
|
export interface ConfigFieldDef {
|
||||||
type: "string" | "number" | "select" | "multiselect"
|
type: "string" | "number" | "select"
|
||||||
label: string
|
label: string
|
||||||
required?: boolean
|
required?: boolean
|
||||||
description?: string
|
description?: string
|
||||||
secret?: boolean
|
secret?: boolean
|
||||||
defaultValue?: string | number | string[]
|
defaultValue?: string | number
|
||||||
options?: { label: string; value: string }[]
|
options?: { label: string; value: string }[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,8 +23,6 @@ export interface SourceDefinition {
|
|||||||
name: string
|
name: string
|
||||||
description: string
|
description: string
|
||||||
alwaysEnabled?: boolean
|
alwaysEnabled?: boolean
|
||||||
/** When true, secret fields are stored as per-user credentials via /api/sources/:id/credentials. */
|
|
||||||
perUserCredentials?: boolean
|
|
||||||
fields: Record<string, ConfigFieldDef>
|
fields: Record<string, ConfigFieldDef>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,108 +45,13 @@ const sourceDefinitions: SourceDefinition[] = [
|
|||||||
name: "WeatherKit",
|
name: "WeatherKit",
|
||||||
description: "Apple WeatherKit weather data. Requires Apple Developer credentials.",
|
description: "Apple WeatherKit weather data. Requires Apple Developer credentials.",
|
||||||
fields: {
|
fields: {
|
||||||
privateKey: {
|
privateKey: { type: "string", label: "Private Key", required: true, secret: true, description: "Apple WeatherKit private key (PEM format)" },
|
||||||
type: "string",
|
|
||||||
label: "Private Key",
|
|
||||||
required: true,
|
|
||||||
secret: true,
|
|
||||||
description: "Apple WeatherKit private key (PEM format)",
|
|
||||||
},
|
|
||||||
keyId: { type: "string", label: "Key ID", required: true, secret: true },
|
keyId: { type: "string", label: "Key ID", required: true, secret: true },
|
||||||
teamId: { type: "string", label: "Team ID", required: true, secret: true },
|
teamId: { type: "string", label: "Team ID", required: true, secret: true },
|
||||||
serviceId: { type: "string", label: "Service ID", required: true, secret: true },
|
serviceId: { type: "string", label: "Service ID", required: true, secret: true },
|
||||||
units: {
|
units: { type: "select", label: "Units", options: [{ label: "Metric", value: "metric" }, { label: "Imperial", value: "imperial" }], defaultValue: "metric" },
|
||||||
type: "select",
|
hourlyLimit: { type: "number", label: "Hourly Forecast Limit", defaultValue: 12, description: "Number of hourly forecasts to include" },
|
||||||
label: "Units",
|
dailyLimit: { type: "number", label: "Daily Forecast Limit", defaultValue: 7, description: "Number of daily forecasts to include" },
|
||||||
options: [
|
|
||||||
{ label: "Metric", value: "metric" },
|
|
||||||
{ label: "Imperial", value: "imperial" },
|
|
||||||
],
|
|
||||||
defaultValue: "metric",
|
|
||||||
},
|
|
||||||
hourlyLimit: {
|
|
||||||
type: "number",
|
|
||||||
label: "Hourly Forecast Limit",
|
|
||||||
defaultValue: 12,
|
|
||||||
description: "Number of hourly forecasts to include",
|
|
||||||
},
|
|
||||||
dailyLimit: {
|
|
||||||
type: "number",
|
|
||||||
label: "Daily Forecast Limit",
|
|
||||||
defaultValue: 7,
|
|
||||||
description: "Number of daily forecasts to include",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "aelis.caldav",
|
|
||||||
name: "CalDAV",
|
|
||||||
description: "Calendar events from any CalDAV server (Nextcloud, Radicale, Baikal, etc.).",
|
|
||||||
perUserCredentials: true,
|
|
||||||
fields: {
|
|
||||||
serverUrl: {
|
|
||||||
type: "string",
|
|
||||||
label: "Server URL",
|
|
||||||
required: true,
|
|
||||||
secret: false,
|
|
||||||
description: "CalDAV server URL (e.g. https://nextcloud.example.com/remote.php/dav)",
|
|
||||||
},
|
|
||||||
username: {
|
|
||||||
type: "string",
|
|
||||||
label: "Username",
|
|
||||||
required: true,
|
|
||||||
secret: false,
|
|
||||||
},
|
|
||||||
password: {
|
|
||||||
type: "string",
|
|
||||||
label: "Password",
|
|
||||||
required: true,
|
|
||||||
secret: true,
|
|
||||||
},
|
|
||||||
lookAheadDays: {
|
|
||||||
type: "number",
|
|
||||||
label: "Look-ahead Days",
|
|
||||||
defaultValue: 0,
|
|
||||||
description: "Number of additional days beyond today to fetch events for",
|
|
||||||
},
|
|
||||||
timeZone: {
|
|
||||||
type: "string",
|
|
||||||
label: "Timezone",
|
|
||||||
description: 'IANA timezone for determining "today" (e.g. Europe/London). Defaults to UTC.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "aelis.tfl",
|
|
||||||
name: "TfL",
|
|
||||||
description: "Transport for London tube line status alerts.",
|
|
||||||
fields: {
|
|
||||||
lines: {
|
|
||||||
type: "multiselect",
|
|
||||||
label: "Lines",
|
|
||||||
description: "Lines to monitor. Leave empty for all lines.",
|
|
||||||
defaultValue: [],
|
|
||||||
options: [
|
|
||||||
{ label: "Bakerloo", value: "bakerloo" },
|
|
||||||
{ label: "Central", value: "central" },
|
|
||||||
{ label: "Circle", value: "circle" },
|
|
||||||
{ label: "District", value: "district" },
|
|
||||||
{ label: "Hammersmith & City", value: "hammersmith-city" },
|
|
||||||
{ label: "Jubilee", value: "jubilee" },
|
|
||||||
{ label: "Metropolitan", value: "metropolitan" },
|
|
||||||
{ label: "Northern", value: "northern" },
|
|
||||||
{ label: "Piccadilly", value: "piccadilly" },
|
|
||||||
{ label: "Victoria", value: "victoria" },
|
|
||||||
{ label: "Waterloo & City", value: "waterloo-city" },
|
|
||||||
{ label: "Lioness", value: "lioness" },
|
|
||||||
{ label: "Mildmay", value: "mildmay" },
|
|
||||||
{ label: "Windrush", value: "windrush" },
|
|
||||||
{ label: "Weaver", value: "weaver" },
|
|
||||||
{ label: "Suffragette", value: "suffragette" },
|
|
||||||
{ label: "Liberty", value: "liberty" },
|
|
||||||
{ label: "Elizabeth", value: "elizabeth" },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@@ -157,7 +60,9 @@ export function fetchSources(): Promise<SourceDefinition[]> {
|
|||||||
return Promise.resolve(sourceDefinitions)
|
return Promise.resolve(sourceDefinitions)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchSourceConfig(sourceId: string): Promise<SourceConfig | null> {
|
export async function fetchSourceConfig(
|
||||||
|
sourceId: string,
|
||||||
|
): Promise<SourceConfig | null> {
|
||||||
const res = await fetch(`${serverBase()}/sources/${sourceId}`, {
|
const res = await fetch(`${serverBase()}/sources/${sourceId}`, {
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
})
|
})
|
||||||
@@ -168,13 +73,15 @@ export async function fetchSourceConfig(sourceId: string): Promise<SourceConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchConfigs(): Promise<SourceConfig[]> {
|
export async function fetchConfigs(): Promise<SourceConfig[]> {
|
||||||
const results = await Promise.all(sourceDefinitions.map((s) => fetchSourceConfig(s.id)))
|
const results = await Promise.all(
|
||||||
|
sourceDefinitions.map((s) => fetchSourceConfig(s.id)),
|
||||||
|
)
|
||||||
return results.filter((c): c is SourceConfig => c !== null)
|
return results.filter((c): c is SourceConfig => c !== null)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function replaceSource(
|
export async function replaceSource(
|
||||||
sourceId: string,
|
sourceId: string,
|
||||||
body: { enabled: boolean; config: unknown; credentials?: Record<string, unknown> },
|
body: { enabled: boolean; config: unknown },
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const res = await fetch(`${serverBase()}/sources/${sourceId}`, {
|
const res = await fetch(`${serverBase()}/sources/${sourceId}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
@@ -204,22 +111,6 @@ export async function updateProviderConfig(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateSourceCredentials(
|
|
||||||
sourceId: string,
|
|
||||||
credentials: Record<string, unknown>,
|
|
||||||
): Promise<void> {
|
|
||||||
const res = await fetch(`${serverBase()}/sources/${sourceId}/credentials`, {
|
|
||||||
method: "PUT",
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
credentials: "include",
|
|
||||||
body: JSON.stringify(credentials),
|
|
||||||
})
|
|
||||||
if (!res.ok) {
|
|
||||||
const data = (await res.json()) as { error?: string }
|
|
||||||
throw new Error(data.error ?? `Failed to update credentials: ${res.status}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LocationInput {
|
export interface LocationInput {
|
||||||
lat: number
|
lat: number
|
||||||
lng: number
|
lng: number
|
||||||
|
|||||||
@@ -3,11 +3,10 @@ import { StrictMode } from "react"
|
|||||||
import { createRoot } from "react-dom/client"
|
import { createRoot } from "react-dom/client"
|
||||||
|
|
||||||
import "./index.css"
|
import "./index.css"
|
||||||
|
import App from "./App.tsx"
|
||||||
import { ThemeProvider } from "@/components/theme-provider.tsx"
|
import { ThemeProvider } from "@/components/theme-provider.tsx"
|
||||||
import { Toaster } from "@/components/ui/sonner.tsx"
|
import { Toaster } from "@/components/ui/sonner.tsx"
|
||||||
|
|
||||||
import App from "./App.tsx"
|
|
||||||
|
|
||||||
const queryClient = new QueryClient({
|
const queryClient = new QueryClient({
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
queries: {
|
queries: {
|
||||||
@@ -25,5 +24,5 @@ createRoot(document.getElementById("root")!).render(
|
|||||||
<Toaster />
|
<Toaster />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</StrictMode>,
|
</StrictMode>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
import { Route as rootRoute } from "./routes/__root"
|
import { Route as rootRoute } from "./routes/__root"
|
||||||
import { Route as dashboardRoute } from "./routes/_dashboard"
|
|
||||||
import { Route as dashboardFeedRoute } from "./routes/_dashboard/feed"
|
|
||||||
import { Route as dashboardIndexRoute } from "./routes/_dashboard/index"
|
|
||||||
import { Route as dashboardSourceRoute } from "./routes/_dashboard/sources.$sourceId"
|
|
||||||
import { Route as loginRoute } from "./routes/login"
|
import { Route as loginRoute } from "./routes/login"
|
||||||
|
import { Route as dashboardRoute } from "./routes/_dashboard"
|
||||||
|
import { Route as dashboardIndexRoute } from "./routes/_dashboard/index"
|
||||||
|
import { Route as dashboardFeedRoute } from "./routes/_dashboard/feed"
|
||||||
|
import { Route as dashboardSourceRoute } from "./routes/_dashboard/sources.$sourceId"
|
||||||
|
|
||||||
export const routeTree = rootRoute.addChildren([
|
export const routeTree = rootRoute.addChildren([
|
||||||
loginRoute,
|
loginRoute,
|
||||||
dashboardRoute.addChildren([dashboardIndexRoute, dashboardFeedRoute, dashboardSourceRoute]),
|
dashboardRoute.addChildren([
|
||||||
|
dashboardIndexRoute,
|
||||||
|
dashboardFeedRoute,
|
||||||
|
dashboardSourceRoute,
|
||||||
|
]),
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import type { QueryClient } from "@tanstack/react-query"
|
|
||||||
|
|
||||||
import { createRootRouteWithContext, Outlet } from "@tanstack/react-router"
|
import { createRootRouteWithContext, Outlet } from "@tanstack/react-router"
|
||||||
|
import type { QueryClient } from "@tanstack/react-query"
|
||||||
import { TooltipProvider } from "@/components/ui/tooltip"
|
import { TooltipProvider } from "@/components/ui/tooltip"
|
||||||
|
|
||||||
export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()({
|
export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()({
|
||||||
|
|||||||
@@ -1,19 +1,11 @@
|
|||||||
|
import { createRoute, Outlet, redirect, useMatchRoute, useNavigate, Link } from "@tanstack/react-router"
|
||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
||||||
import {
|
|
||||||
createRoute,
|
|
||||||
Outlet,
|
|
||||||
redirect,
|
|
||||||
useMatchRoute,
|
|
||||||
useNavigate,
|
|
||||||
Link,
|
|
||||||
} from "@tanstack/react-router"
|
|
||||||
import {
|
import {
|
||||||
Calendar,
|
Calendar,
|
||||||
CalendarDays,
|
CalendarDays,
|
||||||
CircleDot,
|
CircleDot,
|
||||||
CloudSun,
|
CloudSun,
|
||||||
Loader2,
|
Loader2,
|
||||||
TrainFront,
|
|
||||||
LogOut,
|
LogOut,
|
||||||
MapPin,
|
MapPin,
|
||||||
Rss,
|
Rss,
|
||||||
@@ -21,6 +13,9 @@ import {
|
|||||||
TriangleAlert,
|
TriangleAlert,
|
||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
|
|
||||||
|
import { fetchConfigs, fetchSources } from "@/lib/api"
|
||||||
|
import { getSession, signOut } from "@/lib/auth"
|
||||||
|
|
||||||
import { Alert, AlertDescription } from "@/components/ui/alert"
|
import { Alert, AlertDescription } from "@/components/ui/alert"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Separator } from "@/components/ui/separator"
|
import { Separator } from "@/components/ui/separator"
|
||||||
@@ -39,9 +34,6 @@ import {
|
|||||||
SidebarProvider,
|
SidebarProvider,
|
||||||
SidebarTrigger,
|
SidebarTrigger,
|
||||||
} from "@/components/ui/sidebar"
|
} from "@/components/ui/sidebar"
|
||||||
import { fetchConfigs, fetchSources } from "@/lib/api"
|
|
||||||
import { getSession, signOut } from "@/lib/auth"
|
|
||||||
|
|
||||||
import { Route as rootRoute } from "./__root"
|
import { Route as rootRoute } from "./__root"
|
||||||
|
|
||||||
const SOURCE_ICONS: Record<string, React.ComponentType<{ className?: string }>> = {
|
const SOURCE_ICONS: Record<string, React.ComponentType<{ className?: string }>> = {
|
||||||
@@ -49,7 +41,6 @@ const SOURCE_ICONS: Record<string, React.ComponentType<{ className?: string }>>
|
|||||||
"aelis.weather": CloudSun,
|
"aelis.weather": CloudSun,
|
||||||
"aelis.caldav": CalendarDays,
|
"aelis.caldav": CalendarDays,
|
||||||
"aelis.google-calendar": Calendar,
|
"aelis.google-calendar": Calendar,
|
||||||
"aelis.tfl": TrainFront,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Route = createRoute({
|
export const Route = createRoute({
|
||||||
@@ -119,12 +110,7 @@ function DashboardLayout() {
|
|||||||
<p className="truncate text-sm font-medium">{user.name}</p>
|
<p className="truncate text-sm font-medium">{user.name}</p>
|
||||||
<p className="truncate text-xs text-muted-foreground">{user.email}</p>
|
<p className="truncate text-xs text-muted-foreground">{user.email}</p>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button variant="ghost" size="icon" className="size-7 shrink-0" onClick={() => logoutMutation.mutate()}>
|
||||||
variant="ghost"
|
|
||||||
size="icon"
|
|
||||||
className="size-7 shrink-0"
|
|
||||||
onClick={() => logoutMutation.mutate()}
|
|
||||||
>
|
|
||||||
<LogOut className="size-3.5" />
|
<LogOut className="size-3.5" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@@ -135,7 +121,10 @@ function DashboardLayout() {
|
|||||||
<SidebarGroupContent>
|
<SidebarGroupContent>
|
||||||
<SidebarMenu>
|
<SidebarMenu>
|
||||||
<SidebarMenuItem>
|
<SidebarMenuItem>
|
||||||
<SidebarMenuButton isActive={!!matchRoute({ to: "/" })} asChild>
|
<SidebarMenuButton
|
||||||
|
isActive={!!matchRoute({ to: "/" })}
|
||||||
|
asChild
|
||||||
|
>
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<Server className="size-4" />
|
<Server className="size-4" />
|
||||||
<span>Server</span>
|
<span>Server</span>
|
||||||
@@ -143,7 +132,10 @@ function DashboardLayout() {
|
|||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
<SidebarMenuItem>
|
<SidebarMenuItem>
|
||||||
<SidebarMenuButton isActive={!!matchRoute({ to: "/feed" })} asChild>
|
<SidebarMenuButton
|
||||||
|
isActive={!!matchRoute({ to: "/feed" })}
|
||||||
|
asChild
|
||||||
|
>
|
||||||
<Link to="/feed">
|
<Link to="/feed">
|
||||||
<Rss className="size-4" />
|
<Rss className="size-4" />
|
||||||
<span>Feed</span>
|
<span>Feed</span>
|
||||||
@@ -165,12 +157,7 @@ function DashboardLayout() {
|
|||||||
return (
|
return (
|
||||||
<SidebarMenuItem key={source.id}>
|
<SidebarMenuItem key={source.id}>
|
||||||
<SidebarMenuButton
|
<SidebarMenuButton
|
||||||
isActive={
|
isActive={!!matchRoute({ to: "/sources/$sourceId", params: { sourceId: source.id } })}
|
||||||
!!matchRoute({
|
|
||||||
to: "/sources/$sourceId",
|
|
||||||
params: { sourceId: source.id },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
asChild
|
asChild
|
||||||
>
|
>
|
||||||
<Link to="/sources/$sourceId" params={{ sourceId: source.id }}>
|
<Link to="/sources/$sourceId" params={{ sourceId: source.id }}>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { createRoute } from "@tanstack/react-router"
|
import { createRoute } from "@tanstack/react-router"
|
||||||
|
|
||||||
import { FeedPanel } from "@/components/feed-panel"
|
import { FeedPanel } from "@/components/feed-panel"
|
||||||
|
|
||||||
import { Route as dashboardRoute } from "../_dashboard"
|
import { Route as dashboardRoute } from "../_dashboard"
|
||||||
|
|
||||||
export const Route = createRoute({
|
export const Route = createRoute({
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { createRoute } from "@tanstack/react-router"
|
import { createRoute } from "@tanstack/react-router"
|
||||||
|
|
||||||
import { GeneralSettingsPanel } from "@/components/general-settings-panel"
|
import { GeneralSettingsPanel } from "@/components/general-settings-panel"
|
||||||
|
|
||||||
import { Route as dashboardRoute } from "../_dashboard"
|
import { Route as dashboardRoute } from "../_dashboard"
|
||||||
|
|
||||||
export const Route = createRoute({
|
export const Route = createRoute({
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { useQuery, useQueryClient } from "@tanstack/react-query"
|
|
||||||
import { createRoute } from "@tanstack/react-router"
|
import { createRoute } from "@tanstack/react-router"
|
||||||
|
import { useQuery, useQueryClient } from "@tanstack/react-query"
|
||||||
|
|
||||||
import { SourceConfigPanel } from "@/components/source-config-panel"
|
|
||||||
import { fetchSources } from "@/lib/api"
|
import { fetchSources } from "@/lib/api"
|
||||||
|
import { SourceConfigPanel } from "@/components/source-config-panel"
|
||||||
import { Route as dashboardRoute } from "../_dashboard"
|
import { Route as dashboardRoute } from "../_dashboard"
|
||||||
|
|
||||||
export const Route = createRoute({
|
export const Route = createRoute({
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import { useQueryClient } from "@tanstack/react-query"
|
|
||||||
import { createRoute, useNavigate } from "@tanstack/react-router"
|
import { createRoute, useNavigate } from "@tanstack/react-router"
|
||||||
|
import { useQueryClient } from "@tanstack/react-query"
|
||||||
|
|
||||||
import type { AuthSession } from "@/lib/auth"
|
import type { AuthSession } from "@/lib/auth"
|
||||||
|
|
||||||
import { LoginPage } from "@/components/login-page"
|
import { LoginPage } from "@/components/login-page"
|
||||||
|
|
||||||
import { Route as rootRoute } from "./__root"
|
import { Route as rootRoute } from "./__root"
|
||||||
|
|
||||||
export const Route = createRoute({
|
export const Route = createRoute({
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"lib": ["ES2022", "DOM"],
|
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"types": ["vite/client"],
|
"types": ["vite/client"],
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"allowImportingTsExtensions": true,
|
"allowImportingTsExtensions": true,
|
||||||
"verbatimModuleSyntax": true,
|
"verbatimModuleSyntax": true,
|
||||||
@@ -15,12 +16,14 @@
|
|||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
"erasableSyntaxOnly": true,
|
"erasableSyntaxOnly": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noUncheckedSideEffectImports": true,
|
"noUncheckedSideEffectImports": true,
|
||||||
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": ["./src/*"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
{
|
{
|
||||||
"files": [],
|
"files": [],
|
||||||
"references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }],
|
"references": [
|
||||||
|
{ "path": "./tsconfig.app.json" },
|
||||||
|
{ "path": "./tsconfig.node.json" }
|
||||||
|
],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": ["./src/*"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,14 @@
|
|||||||
"types": ["node"],
|
"types": ["node"],
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"allowImportingTsExtensions": true,
|
"allowImportingTsExtensions": true,
|
||||||
"verbatimModuleSyntax": true,
|
"verbatimModuleSyntax": true,
|
||||||
"moduleDetection": "force",
|
"moduleDetection": "force",
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"noUnusedParameters": true,
|
"noUnusedParameters": true,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import path from "path"
|
||||||
import tailwindcss from "@tailwindcss/vite"
|
import tailwindcss from "@tailwindcss/vite"
|
||||||
import react from "@vitejs/plugin-react"
|
import react from "@vitejs/plugin-react"
|
||||||
import path from "path"
|
|
||||||
import { defineConfig } from "vite"
|
import { defineConfig } from "vite"
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ DATABASE_URL=postgresql://user:password@localhost:5432/aris
|
|||||||
BETTER_AUTH_SECRET=
|
BETTER_AUTH_SECRET=
|
||||||
|
|
||||||
# Encryption key for source credentials at rest (32 bytes, generate with: openssl rand -base64 32)
|
# Encryption key for source credentials at rest (32 bytes, generate with: openssl rand -base64 32)
|
||||||
CREDENTIAL_ENCRYPTION_KEY=
|
CREDENTIALS_ENCRYPTION_KEY=
|
||||||
|
|
||||||
# Base URL of the backend
|
# Base URL of the backend
|
||||||
BETTER_AUTH_URL=http://localhost:3000
|
BETTER_AUTH_URL=http://localhost:3000
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/server.ts",
|
"main": "src/server.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "bun run --watch --inspect=0.0.0.0:6499 src/server.ts",
|
"dev": "bun run --watch src/server.ts",
|
||||||
"start": "bun run src/server.ts",
|
"start": "bun run src/server.ts",
|
||||||
"test": "bun test src/",
|
"test": "bun test src/",
|
||||||
"db:generate": "bunx drizzle-kit generate",
|
"db:generate": "bunx drizzle-kit generate",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { describe, expect, test } from "bun:test"
|
|
||||||
import { Hono } from "hono"
|
import { Hono } from "hono"
|
||||||
|
import { describe, expect, test } from "bun:test"
|
||||||
|
|
||||||
import type { Auth } from "./index.ts"
|
import type { Auth } from "./index.ts"
|
||||||
import type { AuthSession, AuthUser } from "./session.ts"
|
import type { AuthSession, AuthUser } from "./session.ts"
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
import { describe, expect, test } from "bun:test"
|
|
||||||
|
|
||||||
import { CalDavSourceProvider } from "./provider.ts"
|
|
||||||
|
|
||||||
describe("CalDavSourceProvider", () => {
|
|
||||||
const provider = new CalDavSourceProvider()
|
|
||||||
|
|
||||||
test("sourceId is aelis.caldav", () => {
|
|
||||||
expect(provider.sourceId).toBe("aelis.caldav")
|
|
||||||
})
|
|
||||||
|
|
||||||
test("throws when credentials are null", async () => {
|
|
||||||
const config = { serverUrl: "https://caldav.icloud.com", username: "user@icloud.com" }
|
|
||||||
await expect(provider.feedSourceForUser("user-1", config, null)).rejects.toThrow(
|
|
||||||
"No CalDAV credentials configured",
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("throws when credentials are missing password", async () => {
|
|
||||||
const config = { serverUrl: "https://caldav.icloud.com", username: "user@icloud.com" }
|
|
||||||
await expect(provider.feedSourceForUser("user-1", config, {})).rejects.toThrow(
|
|
||||||
"password must be a string",
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("throws when config is missing serverUrl", async () => {
|
|
||||||
const credentials = { password: "app-specific-password" }
|
|
||||||
await expect(
|
|
||||||
provider.feedSourceForUser("user-1", { username: "user@icloud.com" }, credentials),
|
|
||||||
).rejects.toThrow("Invalid CalDAV config")
|
|
||||||
})
|
|
||||||
|
|
||||||
test("throws when config is missing username", async () => {
|
|
||||||
const credentials = { password: "app-specific-password" }
|
|
||||||
await expect(
|
|
||||||
provider.feedSourceForUser("user-1", { serverUrl: "https://caldav.icloud.com" }, credentials),
|
|
||||||
).rejects.toThrow("Invalid CalDAV config")
|
|
||||||
})
|
|
||||||
|
|
||||||
test("throws when config has extra keys", async () => {
|
|
||||||
const config = {
|
|
||||||
serverUrl: "https://caldav.icloud.com",
|
|
||||||
username: "user@icloud.com",
|
|
||||||
extra: true,
|
|
||||||
}
|
|
||||||
const credentials = { password: "app-specific-password" }
|
|
||||||
await expect(provider.feedSourceForUser("user-1", config, credentials)).rejects.toThrow(
|
|
||||||
"Invalid CalDAV config",
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("throws when credentials have extra keys", async () => {
|
|
||||||
const config = { serverUrl: "https://caldav.icloud.com", username: "user@icloud.com" }
|
|
||||||
const credentials = { password: "app-specific-password", extra: true }
|
|
||||||
await expect(provider.feedSourceForUser("user-1", config, credentials)).rejects.toThrow(
|
|
||||||
"extra must be removed",
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("returns CalDavSource with valid config and credentials", async () => {
|
|
||||||
const config = {
|
|
||||||
serverUrl: "https://caldav.icloud.com",
|
|
||||||
username: "user@icloud.com",
|
|
||||||
lookAheadDays: 3,
|
|
||||||
timeZone: "Europe/London",
|
|
||||||
}
|
|
||||||
const credentials = { password: "app-specific-password" }
|
|
||||||
|
|
||||||
const source = await provider.feedSourceForUser("user-1", config, credentials)
|
|
||||||
expect(source).toBeDefined()
|
|
||||||
expect(source.id).toBe("aelis.caldav")
|
|
||||||
})
|
|
||||||
|
|
||||||
test("returns CalDavSource with minimal config", async () => {
|
|
||||||
const config = {
|
|
||||||
serverUrl: "https://caldav.icloud.com",
|
|
||||||
username: "user@icloud.com",
|
|
||||||
}
|
|
||||||
const credentials = { password: "app-specific-password" }
|
|
||||||
|
|
||||||
const source = await provider.feedSourceForUser("user-1", config, credentials)
|
|
||||||
expect(source).toBeDefined()
|
|
||||||
expect(source.id).toBe("aelis.caldav")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
import { CalDavSource } from "@aelis/source-caldav"
|
|
||||||
import { type } from "arktype"
|
|
||||||
|
|
||||||
import type { FeedSourceProvider } from "../session/feed-source-provider.ts"
|
|
||||||
|
|
||||||
import { InvalidSourceCredentialsError } from "../sources/errors.ts"
|
|
||||||
|
|
||||||
const caldavConfig = type({
|
|
||||||
"+": "reject",
|
|
||||||
serverUrl: "string",
|
|
||||||
username: "string",
|
|
||||||
"lookAheadDays?": "number",
|
|
||||||
"timeZone?": "string",
|
|
||||||
})
|
|
||||||
|
|
||||||
const caldavCredentials = type({
|
|
||||||
"+": "reject",
|
|
||||||
password: "string",
|
|
||||||
})
|
|
||||||
|
|
||||||
export class CalDavSourceProvider implements FeedSourceProvider {
|
|
||||||
readonly sourceId = "aelis.caldav"
|
|
||||||
readonly configSchema = caldavConfig
|
|
||||||
|
|
||||||
async feedSourceForUser(
|
|
||||||
_userId: string,
|
|
||||||
config: unknown,
|
|
||||||
credentials: unknown,
|
|
||||||
): Promise<CalDavSource> {
|
|
||||||
const parsed = caldavConfig(config)
|
|
||||||
if (parsed instanceof type.errors) {
|
|
||||||
throw new Error(`Invalid CalDAV config: ${parsed.summary}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!credentials) {
|
|
||||||
throw new InvalidSourceCredentialsError("aelis.caldav", "No CalDAV credentials configured")
|
|
||||||
}
|
|
||||||
|
|
||||||
const creds = caldavCredentials(credentials)
|
|
||||||
if (creds instanceof type.errors) {
|
|
||||||
throw new InvalidSourceCredentialsError("aelis.caldav", creds.summary)
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CalDavSource({
|
|
||||||
serverUrl: parsed.serverUrl,
|
|
||||||
authMethod: "basic",
|
|
||||||
username: parsed.username,
|
|
||||||
password: creds.password,
|
|
||||||
lookAheadDays: parsed.lookAheadDays,
|
|
||||||
timeZone: parsed.timeZone,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,9 @@
|
|||||||
import type { PgDatabase } from "drizzle-orm/pg-core"
|
|
||||||
|
|
||||||
import { SQL } from "bun"
|
import { SQL } from "bun"
|
||||||
import { drizzle, type BunSQLQueryResultHKT } from "drizzle-orm/bun-sql"
|
import { drizzle, type BunSQLDatabase } from "drizzle-orm/bun-sql"
|
||||||
|
|
||||||
import * as schema from "./schema.ts"
|
import * as schema from "./schema.ts"
|
||||||
|
|
||||||
/** Covers both the top-level drizzle instance and transaction handles. */
|
export type Database = BunSQLDatabase<typeof schema>
|
||||||
export type Database = PgDatabase<BunSQLQueryResultHKT, typeof schema>
|
|
||||||
|
|
||||||
export interface DatabaseConnection {
|
export interface DatabaseConnection {
|
||||||
db: Database
|
db: Database
|
||||||
|
|||||||
@@ -47,3 +47,5 @@ export function createFeedEnhancer(config: FeedEnhancerConfig): FeedEnhancer {
|
|||||||
return mergeEnhancement(items, result, currentTime)
|
return mergeEnhancement(items, result, currentTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type { EnhancementResult } from "./schema.ts"
|
|||||||
|
|
||||||
import { enhancementResultJsonSchema, parseEnhancementResult } from "./schema.ts"
|
import { enhancementResultJsonSchema, parseEnhancementResult } from "./schema.ts"
|
||||||
|
|
||||||
const DEFAULT_MODEL = "z-ai/glm-4.7-flash"
|
const DEFAULT_MODEL = "openai/gpt-4.1-mini"
|
||||||
const DEFAULT_TIMEOUT_MS = 30_000
|
const DEFAULT_TIMEOUT_MS = 30_000
|
||||||
|
|
||||||
export interface LlmClientConfig {
|
export interface LlmClientConfig {
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ export function buildPrompt(
|
|||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const hasUnfilledSlots =
|
const hasUnfilledSlots =
|
||||||
item.slots && Object.values(item.slots).some((slot) => slot.content === null)
|
item.slots &&
|
||||||
|
Object.values(item.slots).some((slot) => slot.content === null)
|
||||||
|
|
||||||
if (hasUnfilledSlots) {
|
if (hasUnfilledSlots) {
|
||||||
enhanceItems.push({
|
enhanceItems.push({
|
||||||
@@ -78,7 +79,9 @@ export function buildPrompt(
|
|||||||
*/
|
*/
|
||||||
export function hasUnfilledSlots(items: FeedItem[]): boolean {
|
export function hasUnfilledSlots(items: FeedItem[]): boolean {
|
||||||
return items.some(
|
return items.some(
|
||||||
(item) => item.slots && Object.values(item.slots).some((slot) => slot.content === null),
|
(item) =>
|
||||||
|
item.slots &&
|
||||||
|
Object.values(item.slots).some((slot) => slot.content === null),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,20 +129,7 @@ function extractCalendarEntry(item: FeedItem): CalendarEntry | null {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] as const
|
const DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] as const
|
||||||
const MONTHS = [
|
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] as const
|
||||||
"Jan",
|
|
||||||
"Feb",
|
|
||||||
"Mar",
|
|
||||||
"Apr",
|
|
||||||
"May",
|
|
||||||
"Jun",
|
|
||||||
"Jul",
|
|
||||||
"Aug",
|
|
||||||
"Sep",
|
|
||||||
"Oct",
|
|
||||||
"Nov",
|
|
||||||
"Dec",
|
|
||||||
] as const
|
|
||||||
|
|
||||||
function pad2(n: number): string {
|
function pad2(n: number): string {
|
||||||
return n.toString().padStart(2, "0")
|
return n.toString().padStart(2, "0")
|
||||||
@@ -154,11 +144,7 @@ function formatDayShort(date: Date): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formatDayLabel(date: Date, currentTime: Date): string {
|
function formatDayLabel(date: Date, currentTime: Date): string {
|
||||||
const currentDay = Date.UTC(
|
const currentDay = Date.UTC(currentTime.getUTCFullYear(), currentTime.getUTCMonth(), currentTime.getUTCDate())
|
||||||
currentTime.getUTCFullYear(),
|
|
||||||
currentTime.getUTCMonth(),
|
|
||||||
currentTime.getUTCDate(),
|
|
||||||
)
|
|
||||||
const targetDay = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate())
|
const targetDay = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate())
|
||||||
const diffDays = Math.round((targetDay - currentDay) / (1000 * 60 * 60 * 24))
|
const diffDays = Math.round((targetDay - currentDay) / (1000 * 60 * 60 * 24))
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,9 @@ describe("schema sync", () => {
|
|||||||
|
|
||||||
// JSON Schema structure matches
|
// JSON Schema structure matches
|
||||||
const jsonSchema = enhancementResultJsonSchema
|
const jsonSchema = enhancementResultJsonSchema
|
||||||
expect(Object.keys(jsonSchema.properties).sort()).toEqual(Object.keys(payload).sort())
|
expect(Object.keys(jsonSchema.properties).sort()).toEqual(
|
||||||
|
Object.keys(payload).sort(),
|
||||||
|
)
|
||||||
expect([...jsonSchema.required].sort()).toEqual(Object.keys(payload).sort())
|
expect([...jsonSchema.required].sort()).toEqual(Object.keys(payload).sort())
|
||||||
|
|
||||||
// syntheticItems item schema has the right required fields
|
// syntheticItems item schema has the right required fields
|
||||||
@@ -165,7 +167,11 @@ describe("schema sync", () => {
|
|||||||
|
|
||||||
// JSON Schema only allows string or null for slot values
|
// JSON Schema only allows string or null for slot values
|
||||||
const slotValueSchema =
|
const slotValueSchema =
|
||||||
enhancementResultJsonSchema.properties.slotFills.additionalProperties.additionalProperties
|
enhancementResultJsonSchema.properties.slotFills.additionalProperties
|
||||||
expect(slotValueSchema.anyOf).toEqual([{ type: "string" }, { type: "null" }])
|
.additionalProperties
|
||||||
|
expect(slotValueSchema.anyOf).toEqual([
|
||||||
|
{ type: "string" },
|
||||||
|
{ type: "null" },
|
||||||
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { describe, expect, test } from "bun:test"
|
|
||||||
import { randomBytes } from "node:crypto"
|
import { randomBytes } from "node:crypto"
|
||||||
|
import { describe, expect, test } from "bun:test"
|
||||||
|
|
||||||
import { CredentialEncryptor } from "./crypto.ts"
|
import { CredentialEncryptor } from "./crypto.ts"
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,7 @@ import type { FeedSourceProvider } from "../session/feed-source-provider.ts"
|
|||||||
export class LocationSourceProvider implements FeedSourceProvider {
|
export class LocationSourceProvider implements FeedSourceProvider {
|
||||||
readonly sourceId = "aelis.location"
|
readonly sourceId = "aelis.location"
|
||||||
|
|
||||||
async feedSourceForUser(
|
async feedSourceForUser(_userId: string, _config: unknown): Promise<LocationSource> {
|
||||||
_userId: string,
|
|
||||||
_config: unknown,
|
|
||||||
_credentials: unknown,
|
|
||||||
): Promise<LocationSource> {
|
|
||||||
return new LocationSource()
|
return new LocationSource()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,17 +6,14 @@ import { createRequireAdmin } from "./auth/admin-middleware.ts"
|
|||||||
import { registerAuthHandlers } from "./auth/http.ts"
|
import { registerAuthHandlers } from "./auth/http.ts"
|
||||||
import { createAuth } from "./auth/index.ts"
|
import { createAuth } from "./auth/index.ts"
|
||||||
import { createRequireSession } from "./auth/session-middleware.ts"
|
import { createRequireSession } from "./auth/session-middleware.ts"
|
||||||
import { CalDavSourceProvider } from "./caldav/provider.ts"
|
|
||||||
import { createDatabase } from "./db/index.ts"
|
import { createDatabase } from "./db/index.ts"
|
||||||
import { registerFeedHttpHandlers } from "./engine/http.ts"
|
import { registerFeedHttpHandlers } from "./engine/http.ts"
|
||||||
import { createFeedEnhancer } from "./enhancement/enhance-feed.ts"
|
import { createFeedEnhancer } from "./enhancement/enhance-feed.ts"
|
||||||
import { createLlmClient } from "./enhancement/llm-client.ts"
|
import { createLlmClient } from "./enhancement/llm-client.ts"
|
||||||
import { CredentialEncryptor } from "./lib/crypto.ts"
|
|
||||||
import { registerLocationHttpHandlers } from "./location/http.ts"
|
import { registerLocationHttpHandlers } from "./location/http.ts"
|
||||||
import { LocationSourceProvider } from "./location/provider.ts"
|
import { LocationSourceProvider } from "./location/provider.ts"
|
||||||
import { UserSessionManager } from "./session/index.ts"
|
import { UserSessionManager } from "./session/index.ts"
|
||||||
import { registerSourcesHttpHandlers } from "./sources/http.ts"
|
import { registerSourcesHttpHandlers } from "./sources/http.ts"
|
||||||
import { TflSourceProvider } from "./tfl/provider.ts"
|
|
||||||
import { WeatherSourceProvider } from "./weather/provider.ts"
|
import { WeatherSourceProvider } from "./weather/provider.ts"
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
@@ -36,20 +33,9 @@ function main() {
|
|||||||
console.warn("[enhancement] OPENROUTER_API_KEY not set — feed enhancement disabled")
|
console.warn("[enhancement] OPENROUTER_API_KEY not set — feed enhancement disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
const credentialEncryptionKey = process.env.CREDENTIAL_ENCRYPTION_KEY
|
|
||||||
const credentialEncryptor = credentialEncryptionKey
|
|
||||||
? new CredentialEncryptor(credentialEncryptionKey)
|
|
||||||
: null
|
|
||||||
if (!credentialEncryptor) {
|
|
||||||
console.warn(
|
|
||||||
"[credentials] CREDENTIAL_ENCRYPTION_KEY not set — per-user credential storage disabled",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const sessionManager = new UserSessionManager({
|
const sessionManager = new UserSessionManager({
|
||||||
db,
|
db,
|
||||||
providers: [
|
providers: [
|
||||||
new CalDavSourceProvider(),
|
|
||||||
new LocationSourceProvider(),
|
new LocationSourceProvider(),
|
||||||
new WeatherSourceProvider({
|
new WeatherSourceProvider({
|
||||||
credentials: {
|
credentials: {
|
||||||
@@ -59,10 +45,8 @@ function main() {
|
|||||||
serviceId: process.env.WEATHERKIT_SERVICE_ID!,
|
serviceId: process.env.WEATHERKIT_SERVICE_ID!,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
new TflSourceProvider({ apiKey: process.env.TFL_API_KEY! }),
|
|
||||||
],
|
],
|
||||||
feedEnhancer,
|
feedEnhancer,
|
||||||
credentialEncryptor,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const app = new Hono()
|
const app = new Hono()
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ export interface FeedSourceProvider {
|
|||||||
readonly sourceId: string
|
readonly sourceId: string
|
||||||
/** Arktype schema for validating user-provided config. Omit if the source has no config. */
|
/** Arktype schema for validating user-provided config. Omit if the source has no config. */
|
||||||
readonly configSchema?: ConfigSchema
|
readonly configSchema?: ConfigSchema
|
||||||
feedSourceForUser(userId: string, config: unknown, credentials: unknown): Promise<FeedSource>
|
feedSourceForUser(userId: string, config: unknown): Promise<FeedSource>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,6 @@ import { beforeEach, describe, expect, mock, spyOn, test } from "bun:test"
|
|||||||
import type { Database } from "../db/index.ts"
|
import type { Database } from "../db/index.ts"
|
||||||
import type { FeedSourceProvider } from "./feed-source-provider.ts"
|
import type { FeedSourceProvider } from "./feed-source-provider.ts"
|
||||||
|
|
||||||
import { CredentialEncryptor } from "../lib/crypto.ts"
|
|
||||||
import {
|
|
||||||
CredentialStorageUnavailableError,
|
|
||||||
InvalidSourceCredentialsError,
|
|
||||||
} from "../sources/errors.ts"
|
|
||||||
import { SourceNotFoundError } from "../sources/errors.ts"
|
|
||||||
import { UserSessionManager } from "./user-session-manager.ts"
|
import { UserSessionManager } from "./user-session-manager.ts"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,13 +38,6 @@ function getEnabledSourceIds(userId: string): string[] {
|
|||||||
*/
|
*/
|
||||||
let mockFindResult: unknown | undefined
|
let mockFindResult: unknown | undefined
|
||||||
|
|
||||||
/**
|
|
||||||
* Spy for `updateCredentials` calls. Tests can inspect calls via
|
|
||||||
* `mockUpdateCredentialsCalls` or override behavior.
|
|
||||||
*/
|
|
||||||
const mockUpdateCredentialsCalls: Array<{ sourceId: string; credentials: Buffer }> = []
|
|
||||||
let mockUpdateCredentialsError: Error | null = null
|
|
||||||
|
|
||||||
// Mock the sources module so UserSessionManager's DB query returns controlled data.
|
// Mock the sources module so UserSessionManager's DB query returns controlled data.
|
||||||
mock.module("../sources/user-sources.ts", () => ({
|
mock.module("../sources/user-sources.ts", () => ({
|
||||||
sources: (_db: Database, userId: string) => ({
|
sources: (_db: Database, userId: string) => ({
|
||||||
@@ -81,39 +68,10 @@ mock.module("../sources/user-sources.ts", () => ({
|
|||||||
updatedAt: now,
|
updatedAt: now,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async findForUpdate(sourceId: string) {
|
|
||||||
// Delegates to find — row locking is a no-op in tests.
|
|
||||||
if (mockFindResult !== undefined) return mockFindResult
|
|
||||||
const now = new Date()
|
|
||||||
return {
|
|
||||||
id: crypto.randomUUID(),
|
|
||||||
userId,
|
|
||||||
sourceId,
|
|
||||||
enabled: true,
|
|
||||||
config: {},
|
|
||||||
credentials: null,
|
|
||||||
createdAt: now,
|
|
||||||
updatedAt: now,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async updateConfig(_sourceId: string, _update: { enabled?: boolean; config?: unknown }) {
|
|
||||||
// no-op for tests
|
|
||||||
},
|
|
||||||
async upsertConfig(_sourceId: string, _data: { enabled: boolean; config: unknown }) {
|
|
||||||
// no-op for tests
|
|
||||||
},
|
|
||||||
async updateCredentials(sourceId: string, credentials: Buffer) {
|
|
||||||
if (mockUpdateCredentialsError) {
|
|
||||||
throw mockUpdateCredentialsError
|
|
||||||
}
|
|
||||||
mockUpdateCredentialsCalls.push({ sourceId, credentials })
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const fakeDb = {
|
const fakeDb = {} as Database
|
||||||
transaction: <T>(fn: (tx: unknown) => Promise<T>) => fn(fakeDb),
|
|
||||||
} as unknown as Database
|
|
||||||
|
|
||||||
function createStubSource(id: string, items: FeedItem[] = []): FeedSource {
|
function createStubSource(id: string, items: FeedItem[] = []): FeedSource {
|
||||||
return {
|
return {
|
||||||
@@ -135,11 +93,8 @@ function createStubSource(id: string, items: FeedItem[] = []): FeedSource {
|
|||||||
|
|
||||||
function createStubProvider(
|
function createStubProvider(
|
||||||
sourceId: string,
|
sourceId: string,
|
||||||
factory: (
|
factory: (userId: string, config: Record<string, unknown>) => Promise<FeedSource> = async () =>
|
||||||
userId: string,
|
createStubSource(sourceId),
|
||||||
config: Record<string, unknown>,
|
|
||||||
credentials: unknown,
|
|
||||||
) => Promise<FeedSource> = async () => createStubSource(sourceId),
|
|
||||||
): FeedSourceProvider {
|
): FeedSourceProvider {
|
||||||
return { sourceId, feedSourceForUser: factory }
|
return { sourceId, feedSourceForUser: factory }
|
||||||
}
|
}
|
||||||
@@ -161,8 +116,6 @@ const weatherProvider: FeedSourceProvider = {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
enabledByUser.clear()
|
enabledByUser.clear()
|
||||||
mockFindResult = undefined
|
mockFindResult = undefined
|
||||||
mockUpdateCredentialsCalls.length = 0
|
|
||||||
mockUpdateCredentialsError = null
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("UserSessionManager", () => {
|
describe("UserSessionManager", () => {
|
||||||
@@ -728,240 +681,3 @@ describe("UserSessionManager.replaceProvider", () => {
|
|||||||
expect(feedAfter.items[0]!.data.version).toBe(1)
|
expect(feedAfter.items[0]!.data.version).toBe(1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const TEST_ENCRYPTION_KEY = "/bv1nbzC4ozZkT/pcv5oQfl+JAMuMZDUSVDesG2dur8="
|
|
||||||
const testEncryptor = new CredentialEncryptor(TEST_ENCRYPTION_KEY)
|
|
||||||
|
|
||||||
describe("UserSessionManager.updateSourceCredentials", () => {
|
|
||||||
test("encrypts and persists credentials", async () => {
|
|
||||||
setEnabledSources(["test"])
|
|
||||||
const provider = createStubProvider("test")
|
|
||||||
const manager = new UserSessionManager({
|
|
||||||
db: fakeDb,
|
|
||||||
providers: [provider],
|
|
||||||
credentialEncryptor: testEncryptor,
|
|
||||||
})
|
|
||||||
|
|
||||||
await manager.updateSourceCredentials("user-1", "test", { token: "secret-123" })
|
|
||||||
|
|
||||||
expect(mockUpdateCredentialsCalls).toHaveLength(1)
|
|
||||||
expect(mockUpdateCredentialsCalls[0]!.sourceId).toBe("test")
|
|
||||||
|
|
||||||
// Verify the persisted buffer decrypts to the original credentials
|
|
||||||
const decrypted = JSON.parse(testEncryptor.decrypt(mockUpdateCredentialsCalls[0]!.credentials))
|
|
||||||
expect(decrypted).toEqual({ token: "secret-123" })
|
|
||||||
})
|
|
||||||
|
|
||||||
test("throws CredentialStorageUnavailableError when encryptor is not configured", async () => {
|
|
||||||
setEnabledSources(["test"])
|
|
||||||
const provider = createStubProvider("test")
|
|
||||||
const manager = new UserSessionManager({
|
|
||||||
db: fakeDb,
|
|
||||||
providers: [provider],
|
|
||||||
// no credentialEncryptor
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
manager.updateSourceCredentials("user-1", "test", { token: "x" }),
|
|
||||||
).rejects.toBeInstanceOf(CredentialStorageUnavailableError)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("throws SourceNotFoundError for unknown source", async () => {
|
|
||||||
setEnabledSources([])
|
|
||||||
const manager = new UserSessionManager({
|
|
||||||
db: fakeDb,
|
|
||||||
providers: [],
|
|
||||||
credentialEncryptor: testEncryptor,
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
manager.updateSourceCredentials("user-1", "unknown", { token: "x" }),
|
|
||||||
).rejects.toBeInstanceOf(SourceNotFoundError)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("propagates InvalidSourceCredentialsError from provider", async () => {
|
|
||||||
setEnabledSources(["test"])
|
|
||||||
let callCount = 0
|
|
||||||
const provider: FeedSourceProvider = {
|
|
||||||
sourceId: "test",
|
|
||||||
async feedSourceForUser(_userId: string, _config: unknown, _credentials: unknown) {
|
|
||||||
callCount++
|
|
||||||
// Succeed on first call (session creation), throw on refresh
|
|
||||||
if (callCount > 1) {
|
|
||||||
throw new InvalidSourceCredentialsError("test", "bad credentials")
|
|
||||||
}
|
|
||||||
return createStubSource("test")
|
|
||||||
},
|
|
||||||
}
|
|
||||||
const manager = new UserSessionManager({
|
|
||||||
db: fakeDb,
|
|
||||||
providers: [provider],
|
|
||||||
credentialEncryptor: testEncryptor,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Create a session first so the refresh path is exercised
|
|
||||||
await manager.getOrCreate("user-1")
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
manager.updateSourceCredentials("user-1", "test", { token: "bad" }),
|
|
||||||
).rejects.toBeInstanceOf(InvalidSourceCredentialsError)
|
|
||||||
|
|
||||||
// Credentials should still have been persisted before the provider threw
|
|
||||||
expect(mockUpdateCredentialsCalls).toHaveLength(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("refreshes source in active session after credential update", async () => {
|
|
||||||
setEnabledSources(["test"])
|
|
||||||
let receivedCredentials: unknown = null
|
|
||||||
const provider = createStubProvider("test", async (_userId, _config, credentials) => {
|
|
||||||
receivedCredentials = credentials
|
|
||||||
return createStubSource("test")
|
|
||||||
})
|
|
||||||
const manager = new UserSessionManager({
|
|
||||||
db: fakeDb,
|
|
||||||
providers: [provider],
|
|
||||||
credentialEncryptor: testEncryptor,
|
|
||||||
})
|
|
||||||
|
|
||||||
await manager.getOrCreate("user-1")
|
|
||||||
await manager.updateSourceCredentials("user-1", "test", { token: "refreshed" })
|
|
||||||
|
|
||||||
expect(receivedCredentials).toEqual({ token: "refreshed" })
|
|
||||||
})
|
|
||||||
|
|
||||||
test("persists credentials without session refresh when no active session", async () => {
|
|
||||||
setEnabledSources(["test"])
|
|
||||||
const factory = mock(async () => createStubSource("test"))
|
|
||||||
const provider: FeedSourceProvider = { sourceId: "test", feedSourceForUser: factory }
|
|
||||||
const manager = new UserSessionManager({
|
|
||||||
db: fakeDb,
|
|
||||||
providers: [provider],
|
|
||||||
credentialEncryptor: testEncryptor,
|
|
||||||
})
|
|
||||||
|
|
||||||
// No session created — just update credentials
|
|
||||||
await manager.updateSourceCredentials("user-1", "test", { token: "stored" })
|
|
||||||
|
|
||||||
expect(mockUpdateCredentialsCalls).toHaveLength(1)
|
|
||||||
// feedSourceForUser should not have been called (no session to refresh)
|
|
||||||
expect(factory).not.toHaveBeenCalled()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("UserSessionManager.saveSourceConfig", () => {
|
|
||||||
test("upserts config without credentials (existing behavior)", async () => {
|
|
||||||
setEnabledSources(["test"])
|
|
||||||
const factory = mock(async () => createStubSource("test"))
|
|
||||||
const provider: FeedSourceProvider = { sourceId: "test", feedSourceForUser: factory }
|
|
||||||
const manager = new UserSessionManager({
|
|
||||||
db: fakeDb,
|
|
||||||
providers: [provider],
|
|
||||||
credentialEncryptor: testEncryptor,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Create a session first so we can verify the source is refreshed
|
|
||||||
await manager.getOrCreate("user-1")
|
|
||||||
|
|
||||||
await manager.saveSourceConfig("user-1", "test", {
|
|
||||||
enabled: true,
|
|
||||||
config: { key: "value" },
|
|
||||||
})
|
|
||||||
|
|
||||||
// feedSourceForUser called once for session creation, once for upsert refresh
|
|
||||||
expect(factory).toHaveBeenCalledTimes(2)
|
|
||||||
// No credentials should have been persisted
|
|
||||||
expect(mockUpdateCredentialsCalls).toHaveLength(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("upserts config with credentials — persists both and passes credentials to source", async () => {
|
|
||||||
setEnabledSources(["test"])
|
|
||||||
let receivedCredentials: unknown = null
|
|
||||||
const factory = mock(async (_userId: string, _config: unknown, creds: unknown) => {
|
|
||||||
receivedCredentials = creds
|
|
||||||
return createStubSource("test")
|
|
||||||
})
|
|
||||||
const provider: FeedSourceProvider = { sourceId: "test", feedSourceForUser: factory }
|
|
||||||
const manager = new UserSessionManager({
|
|
||||||
db: fakeDb,
|
|
||||||
providers: [provider],
|
|
||||||
credentialEncryptor: testEncryptor,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Create a session so the source refresh path runs
|
|
||||||
await manager.getOrCreate("user-1")
|
|
||||||
|
|
||||||
const creds = { username: "alice", password: "s3cret" }
|
|
||||||
await manager.saveSourceConfig("user-1", "test", {
|
|
||||||
enabled: true,
|
|
||||||
config: { serverUrl: "https://example.com" },
|
|
||||||
credentials: creds,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Credentials were encrypted and persisted
|
|
||||||
expect(mockUpdateCredentialsCalls).toHaveLength(1)
|
|
||||||
const decrypted = JSON.parse(testEncryptor.decrypt(mockUpdateCredentialsCalls[0]!.credentials))
|
|
||||||
expect(decrypted).toEqual(creds)
|
|
||||||
|
|
||||||
// feedSourceForUser received the provided credentials (not null)
|
|
||||||
expect(receivedCredentials).toEqual(creds)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("upserts config with credentials adds source to session when not already present", async () => {
|
|
||||||
// Start with no enabled sources so the session is empty
|
|
||||||
setEnabledSources([])
|
|
||||||
const factory = mock(async () => createStubSource("test"))
|
|
||||||
const provider: FeedSourceProvider = { sourceId: "test", feedSourceForUser: factory }
|
|
||||||
const manager = new UserSessionManager({
|
|
||||||
db: fakeDb,
|
|
||||||
providers: [provider],
|
|
||||||
credentialEncryptor: testEncryptor,
|
|
||||||
})
|
|
||||||
|
|
||||||
const session = await manager.getOrCreate("user-1")
|
|
||||||
expect(session.hasSource("test")).toBe(false)
|
|
||||||
|
|
||||||
// Set mockFindResult to undefined so find() returns a row (simulating the row was just created by upsertConfig)
|
|
||||||
await manager.saveSourceConfig("user-1", "test", {
|
|
||||||
enabled: true,
|
|
||||||
config: {},
|
|
||||||
credentials: { token: "abc" },
|
|
||||||
})
|
|
||||||
|
|
||||||
// Source should now be in the session
|
|
||||||
expect(session.hasSource("test")).toBe(true)
|
|
||||||
expect(mockUpdateCredentialsCalls).toHaveLength(1)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("throws CredentialStorageUnavailableError when credentials provided without encryptor", async () => {
|
|
||||||
setEnabledSources(["test"])
|
|
||||||
const provider = createStubProvider("test")
|
|
||||||
const manager = new UserSessionManager({
|
|
||||||
db: fakeDb,
|
|
||||||
providers: [provider],
|
|
||||||
// No credentialEncryptor
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
manager.saveSourceConfig("user-1", "test", {
|
|
||||||
enabled: true,
|
|
||||||
config: {},
|
|
||||||
credentials: { token: "abc" },
|
|
||||||
}),
|
|
||||||
).rejects.toBeInstanceOf(CredentialStorageUnavailableError)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("throws SourceNotFoundError for unknown provider", async () => {
|
|
||||||
const manager = new UserSessionManager({
|
|
||||||
db: fakeDb,
|
|
||||||
providers: [],
|
|
||||||
credentialEncryptor: testEncryptor,
|
|
||||||
})
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
manager.saveSourceConfig("user-1", "unknown", {
|
|
||||||
enabled: true,
|
|
||||||
config: {},
|
|
||||||
}),
|
|
||||||
).rejects.toBeInstanceOf(SourceNotFoundError)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -5,14 +5,9 @@ import merge from "lodash.merge"
|
|||||||
|
|
||||||
import type { Database } from "../db/index.ts"
|
import type { Database } from "../db/index.ts"
|
||||||
import type { FeedEnhancer } from "../enhancement/enhance-feed.ts"
|
import type { FeedEnhancer } from "../enhancement/enhance-feed.ts"
|
||||||
import type { CredentialEncryptor } from "../lib/crypto.ts"
|
|
||||||
import type { FeedSourceProvider } from "./feed-source-provider.ts"
|
import type { FeedSourceProvider } from "./feed-source-provider.ts"
|
||||||
|
|
||||||
import {
|
import { InvalidSourceConfigError, SourceNotFoundError } from "../sources/errors.ts"
|
||||||
CredentialStorageUnavailableError,
|
|
||||||
InvalidSourceConfigError,
|
|
||||||
SourceNotFoundError,
|
|
||||||
} from "../sources/errors.ts"
|
|
||||||
import { sources } from "../sources/user-sources.ts"
|
import { sources } from "../sources/user-sources.ts"
|
||||||
import { UserSession } from "./user-session.ts"
|
import { UserSession } from "./user-session.ts"
|
||||||
|
|
||||||
@@ -20,7 +15,6 @@ export interface UserSessionManagerConfig {
|
|||||||
db: Database
|
db: Database
|
||||||
providers: FeedSourceProvider[]
|
providers: FeedSourceProvider[]
|
||||||
feedEnhancer?: FeedEnhancer | null
|
feedEnhancer?: FeedEnhancer | null
|
||||||
credentialEncryptor?: CredentialEncryptor | null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UserSessionManager {
|
export class UserSessionManager {
|
||||||
@@ -29,7 +23,7 @@ export class UserSessionManager {
|
|||||||
private readonly db: Database
|
private readonly db: Database
|
||||||
private readonly providers = new Map<string, FeedSourceProvider>()
|
private readonly providers = new Map<string, FeedSourceProvider>()
|
||||||
private readonly feedEnhancer: FeedEnhancer | null
|
private readonly feedEnhancer: FeedEnhancer | null
|
||||||
private readonly encryptor: CredentialEncryptor | null
|
private readonly db: Database
|
||||||
|
|
||||||
constructor(config: UserSessionManagerConfig) {
|
constructor(config: UserSessionManagerConfig) {
|
||||||
this.db = config.db
|
this.db = config.db
|
||||||
@@ -37,7 +31,7 @@ export class UserSessionManager {
|
|||||||
this.providers.set(provider.sourceId, provider)
|
this.providers.set(provider.sourceId, provider)
|
||||||
}
|
}
|
||||||
this.feedEnhancer = config.feedEnhancer ?? null
|
this.feedEnhancer = config.feedEnhancer ?? null
|
||||||
this.encryptor = config.credentialEncryptor ?? null
|
this.db = config.db
|
||||||
}
|
}
|
||||||
|
|
||||||
getProvider(sourceId: string): FeedSourceProvider | undefined {
|
getProvider(sourceId: string): FeedSourceProvider | undefined {
|
||||||
@@ -126,14 +120,14 @@ export class UserSessionManager {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use a transaction with SELECT FOR UPDATE to prevent lost updates
|
// When config is provided, fetch existing to deep-merge before validating.
|
||||||
// when concurrent PATCH requests merge config against the same base.
|
// NOTE: find + updateConfig is not atomic. A concurrent update could
|
||||||
const { existingRow, mergedConfig } = await this.db.transaction(async (tx) => {
|
// read stale config. Use SELECT FOR UPDATE or atomic jsonb merge if
|
||||||
const existingRow = await sources(tx, userId).findForUpdate(sourceId)
|
// this becomes a problem.
|
||||||
|
|
||||||
let mergedConfig: Record<string, unknown> | undefined
|
let mergedConfig: Record<string, unknown> | undefined
|
||||||
if (update.config !== undefined && provider.configSchema) {
|
if (update.config !== undefined && provider.configSchema) {
|
||||||
const existingConfig = (existingRow?.config ?? {}) as Record<string, unknown>
|
const existing = await sources(this.db, userId).find(sourceId)
|
||||||
|
const existingConfig = (existing?.config ?? {}) as Record<string, unknown>
|
||||||
mergedConfig = merge({}, existingConfig, update.config)
|
mergedConfig = merge({}, existingConfig, update.config)
|
||||||
|
|
||||||
const validated = provider.configSchema(mergedConfig)
|
const validated = provider.configSchema(mergedConfig)
|
||||||
@@ -143,14 +137,11 @@ export class UserSessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Throws SourceNotFoundError if the row doesn't exist
|
// Throws SourceNotFoundError if the row doesn't exist
|
||||||
await sources(tx, userId).updateConfig(sourceId, {
|
await sources(this.db, userId).updateConfig(sourceId, {
|
||||||
enabled: update.enabled,
|
enabled: update.enabled,
|
||||||
config: mergedConfig,
|
config: mergedConfig,
|
||||||
})
|
})
|
||||||
|
|
||||||
return { existingRow, mergedConfig }
|
|
||||||
})
|
|
||||||
|
|
||||||
// Refresh the specific source in the active session instead of
|
// Refresh the specific source in the active session instead of
|
||||||
// destroying the entire session.
|
// destroying the entire session.
|
||||||
const session = this.sessions.get(userId)
|
const session = this.sessions.get(userId)
|
||||||
@@ -158,10 +149,7 @@ export class UserSessionManager {
|
|||||||
if (update.enabled === false) {
|
if (update.enabled === false) {
|
||||||
session.removeSource(sourceId)
|
session.removeSource(sourceId)
|
||||||
} else {
|
} else {
|
||||||
const credentials = existingRow?.credentials
|
const source = await provider.feedSourceForUser(userId, mergedConfig ?? {})
|
||||||
? this.decryptCredentials(existingRow.credentials)
|
|
||||||
: null
|
|
||||||
const source = await provider.feedSourceForUser(userId, mergedConfig ?? {}, credentials)
|
|
||||||
session.replaceSource(sourceId, source)
|
session.replaceSource(sourceId, source)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,18 +161,13 @@ export class UserSessionManager {
|
|||||||
* inserts a new row if one doesn't exist and fully replaces config
|
* inserts a new row if one doesn't exist and fully replaces config
|
||||||
* (no merge).
|
* (no merge).
|
||||||
*
|
*
|
||||||
* When `credentials` is provided, they are encrypted and persisted
|
|
||||||
* alongside the config in the same flow, avoiding the race condition
|
|
||||||
* of separate config + credential requests.
|
|
||||||
*
|
|
||||||
* @throws {SourceNotFoundError} if the sourceId has no registered provider
|
* @throws {SourceNotFoundError} if the sourceId has no registered provider
|
||||||
* @throws {InvalidSourceConfigError} if config fails schema validation
|
* @throws {InvalidSourceConfigError} if config fails schema validation
|
||||||
* @throws {CredentialStorageUnavailableError} if credentials are provided but no encryptor is configured
|
|
||||||
*/
|
*/
|
||||||
async saveSourceConfig(
|
async upsertSourceConfig(
|
||||||
userId: string,
|
userId: string,
|
||||||
sourceId: string,
|
sourceId: string,
|
||||||
data: { enabled: boolean; config?: unknown; credentials?: unknown },
|
data: { enabled: boolean; config?: unknown },
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const provider = this.providers.get(sourceId)
|
const provider = this.providers.get(sourceId)
|
||||||
if (!provider) {
|
if (!provider) {
|
||||||
@@ -198,43 +181,18 @@ export class UserSessionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.credentials !== undefined && !this.encryptor) {
|
|
||||||
throw new CredentialStorageUnavailableError()
|
|
||||||
}
|
|
||||||
|
|
||||||
const config = data.config ?? {}
|
const config = data.config ?? {}
|
||||||
|
await sources(this.db, userId).upsertConfig(sourceId, {
|
||||||
// Run the upsert + credential update atomically so a failure in
|
|
||||||
// either step doesn't leave the row in an inconsistent state.
|
|
||||||
const existingRow = await this.db.transaction(async (tx) => {
|
|
||||||
const existing = await sources(tx, userId).find(sourceId)
|
|
||||||
|
|
||||||
await sources(tx, userId).upsertConfig(sourceId, {
|
|
||||||
enabled: data.enabled,
|
enabled: data.enabled,
|
||||||
config,
|
config,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (data.credentials !== undefined && this.encryptor) {
|
|
||||||
const encrypted = this.encryptor.encrypt(JSON.stringify(data.credentials))
|
|
||||||
await sources(tx, userId).updateCredentials(sourceId, encrypted)
|
|
||||||
}
|
|
||||||
|
|
||||||
return existing
|
|
||||||
})
|
|
||||||
|
|
||||||
const session = this.sessions.get(userId)
|
const session = this.sessions.get(userId)
|
||||||
if (session) {
|
if (session) {
|
||||||
if (!data.enabled) {
|
if (!data.enabled) {
|
||||||
session.removeSource(sourceId)
|
session.removeSource(sourceId)
|
||||||
} else {
|
} else {
|
||||||
// Prefer the just-provided credentials over what was in the DB.
|
const source = await provider.feedSourceForUser(userId, config)
|
||||||
let credentials: unknown = null
|
|
||||||
if (data.credentials !== undefined) {
|
|
||||||
credentials = data.credentials
|
|
||||||
} else if (existingRow?.credentials) {
|
|
||||||
credentials = this.decryptCredentials(existingRow.credentials)
|
|
||||||
}
|
|
||||||
const source = await provider.feedSourceForUser(userId, config, credentials)
|
|
||||||
if (session.hasSource(sourceId)) {
|
if (session.hasSource(sourceId)) {
|
||||||
session.replaceSource(sourceId, source)
|
session.replaceSource(sourceId, source)
|
||||||
} else {
|
} else {
|
||||||
@@ -244,44 +202,6 @@ export class UserSessionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates, encrypts, and persists per-user credentials for a source,
|
|
||||||
* then refreshes the active session.
|
|
||||||
*
|
|
||||||
* @throws {SourceNotFoundError} if the source row doesn't exist or has no registered provider
|
|
||||||
* @throws {CredentialStorageUnavailableError} if no CredentialEncryptor is configured
|
|
||||||
*/
|
|
||||||
async updateSourceCredentials(
|
|
||||||
userId: string,
|
|
||||||
sourceId: string,
|
|
||||||
credentials: unknown,
|
|
||||||
): Promise<void> {
|
|
||||||
const provider = this.providers.get(sourceId)
|
|
||||||
if (!provider) {
|
|
||||||
throw new SourceNotFoundError(sourceId, userId)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.encryptor) {
|
|
||||||
throw new CredentialStorageUnavailableError()
|
|
||||||
}
|
|
||||||
|
|
||||||
const encrypted = this.encryptor.encrypt(JSON.stringify(credentials))
|
|
||||||
await sources(this.db, userId).updateCredentials(sourceId, encrypted)
|
|
||||||
|
|
||||||
// Refresh the source in the active session.
|
|
||||||
// If feedSourceForUser throws (e.g. provider rejects the credentials),
|
|
||||||
// the DB already has the new credentials but the session keeps the old
|
|
||||||
// source. The next session creation will pick up the persisted credentials.
|
|
||||||
const session = this.sessions.get(userId)
|
|
||||||
if (session && session.hasSource(sourceId)) {
|
|
||||||
const row = await sources(this.db, userId).find(sourceId)
|
|
||||||
if (row?.enabled) {
|
|
||||||
const source = await provider.feedSourceForUser(userId, row.config ?? {}, credentials)
|
|
||||||
session.replaceSource(sourceId, source)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces a provider and updates all active sessions.
|
* Replaces a provider and updates all active sessions.
|
||||||
* The new provider must have the same sourceId as an existing one.
|
* The new provider must have the same sourceId as an existing one.
|
||||||
@@ -334,12 +254,7 @@ export class UserSessionManager {
|
|||||||
const row = await sources(this.db, session.userId).find(provider.sourceId)
|
const row = await sources(this.db, session.userId).find(provider.sourceId)
|
||||||
if (!row?.enabled) return
|
if (!row?.enabled) return
|
||||||
|
|
||||||
const credentials = row.credentials ? this.decryptCredentials(row.credentials) : null
|
const newSource = await provider.feedSourceForUser(session.userId, row.config ?? {})
|
||||||
const newSource = await provider.feedSourceForUser(
|
|
||||||
session.userId,
|
|
||||||
row.config ?? {},
|
|
||||||
credentials,
|
|
||||||
)
|
|
||||||
session.replaceSource(provider.sourceId, newSource)
|
session.replaceSource(provider.sourceId, newSource)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(
|
console.error(
|
||||||
@@ -356,8 +271,7 @@ export class UserSessionManager {
|
|||||||
for (const row of enabledRows) {
|
for (const row of enabledRows) {
|
||||||
const provider = this.providers.get(row.sourceId)
|
const provider = this.providers.get(row.sourceId)
|
||||||
if (provider) {
|
if (provider) {
|
||||||
const credentials = row.credentials ? this.decryptCredentials(row.credentials) : null
|
promises.push(provider.feedSourceForUser(userId, row.config ?? {}))
|
||||||
promises.push(provider.feedSourceForUser(userId, row.config ?? {}, credentials))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,19 +302,4 @@ export class UserSessionManager {
|
|||||||
|
|
||||||
return new UserSession(userId, feedSources, this.feedEnhancer)
|
return new UserSession(userId, feedSources, this.feedEnhancer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Decrypts a credentials buffer from the DB, returning parsed JSON or null.
|
|
||||||
* Returns null (with a warning) if decryption or parsing fails — e.g. due to
|
|
||||||
* key rotation, data corruption, or malformed JSON.
|
|
||||||
*/
|
|
||||||
private decryptCredentials(credentials: Buffer): unknown {
|
|
||||||
if (!this.encryptor) return null
|
|
||||||
try {
|
|
||||||
return JSON.parse(this.encryptor.decrypt(credentials))
|
|
||||||
} catch (err) {
|
|
||||||
console.warn("[UserSessionManager] Failed to decrypt credentials:", err)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,26 +24,3 @@ export class InvalidSourceConfigError extends Error {
|
|||||||
this.sourceId = sourceId
|
this.sourceId = sourceId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Thrown by providers when credentials fail validation.
|
|
||||||
*/
|
|
||||||
export class InvalidSourceCredentialsError extends Error {
|
|
||||||
readonly sourceId: string
|
|
||||||
|
|
||||||
constructor(sourceId: string, summary: string) {
|
|
||||||
super(summary)
|
|
||||||
this.name = "InvalidSourceCredentialsError"
|
|
||||||
this.sourceId = sourceId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thrown when credential storage is not configured (missing encryption key).
|
|
||||||
*/
|
|
||||||
export class CredentialStorageUnavailableError extends Error {
|
|
||||||
constructor() {
|
|
||||||
super("Credential storage is not configured")
|
|
||||||
this.name = "CredentialStorageUnavailableError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ import type { Database } from "../db/index.ts"
|
|||||||
import type { ConfigSchema, FeedSourceProvider } from "../session/feed-source-provider.ts"
|
import type { ConfigSchema, FeedSourceProvider } from "../session/feed-source-provider.ts"
|
||||||
|
|
||||||
import { mockAuthSessionMiddleware } from "../auth/session-middleware.ts"
|
import { mockAuthSessionMiddleware } from "../auth/session-middleware.ts"
|
||||||
import { CredentialEncryptor } from "../lib/crypto.ts"
|
|
||||||
import { UserSessionManager } from "../session/user-session-manager.ts"
|
import { UserSessionManager } from "../session/user-session-manager.ts"
|
||||||
import { tflConfig } from "../tfl/provider.ts"
|
import { tflConfig } from "../tfl/provider.ts"
|
||||||
import { weatherConfig } from "../weather/provider.ts"
|
import { weatherConfig } from "../weather/provider.ts"
|
||||||
import { InvalidSourceCredentialsError, SourceNotFoundError } from "./errors.ts"
|
import { SourceNotFoundError } from "./errors.ts"
|
||||||
import { registerSourcesHttpHandlers } from "./http.ts"
|
import { registerSourcesHttpHandlers } from "./http.ts"
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -40,7 +39,7 @@ function createStubProvider(sourceId: string, configSchema?: ConfigSchema): Feed
|
|||||||
return {
|
return {
|
||||||
sourceId,
|
sourceId,
|
||||||
configSchema,
|
configSchema,
|
||||||
async feedSourceForUser(_userId: string, _config: unknown, _credentials: unknown) {
|
async feedSourceForUser() {
|
||||||
return createStubSource(sourceId)
|
return createStubSource(sourceId)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -80,9 +79,6 @@ function createInMemoryStore() {
|
|||||||
async find(sourceId: string) {
|
async find(sourceId: string) {
|
||||||
return rows.get(key(userId, sourceId))
|
return rows.get(key(userId, sourceId))
|
||||||
},
|
},
|
||||||
async findForUpdate(sourceId: string) {
|
|
||||||
return rows.get(key(userId, sourceId))
|
|
||||||
},
|
|
||||||
async updateConfig(sourceId: string, update: { enabled?: boolean; config?: unknown }) {
|
async updateConfig(sourceId: string, update: { enabled?: boolean; config?: unknown }) {
|
||||||
const existing = rows.get(key(userId, sourceId))
|
const existing = rows.get(key(userId, sourceId))
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
@@ -109,12 +105,6 @@ function createInMemoryStore() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async updateCredentials(sourceId: string, _credentials: Buffer) {
|
|
||||||
const existing = rows.get(key(userId, sourceId))
|
|
||||||
if (!existing) {
|
|
||||||
throw new SourceNotFoundError(sourceId, userId)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -128,9 +118,7 @@ mock.module("../sources/user-sources.ts", () => ({
|
|||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const fakeDb = {
|
const fakeDb = {} as Database
|
||||||
transaction: <T>(fn: (tx: unknown) => Promise<T>) => fn(fakeDb),
|
|
||||||
} as unknown as Database
|
|
||||||
|
|
||||||
function createApp(providers: FeedSourceProvider[], userId?: string) {
|
function createApp(providers: FeedSourceProvider[], userId?: string) {
|
||||||
const sessionManager = new UserSessionManager({ providers, db: fakeDb })
|
const sessionManager = new UserSessionManager({ providers, db: fakeDb })
|
||||||
@@ -154,30 +142,6 @@ function get(app: Hono, sourceId: string) {
|
|||||||
return app.request(`/api/sources/${sourceId}`, { method: "GET" })
|
return app.request(`/api/sources/${sourceId}`, { method: "GET" })
|
||||||
}
|
}
|
||||||
|
|
||||||
const TEST_ENCRYPTION_KEY = "/bv1nbzC4ozZkT/pcv5oQfl+JAMuMZDUSVDesG2dur8="
|
|
||||||
|
|
||||||
function createAppWithEncryptor(providers: FeedSourceProvider[], userId?: string) {
|
|
||||||
const sessionManager = new UserSessionManager({
|
|
||||||
providers,
|
|
||||||
db: fakeDb,
|
|
||||||
credentialEncryptor: new CredentialEncryptor(TEST_ENCRYPTION_KEY),
|
|
||||||
})
|
|
||||||
const app = new Hono()
|
|
||||||
registerSourcesHttpHandlers(app, {
|
|
||||||
sessionManager,
|
|
||||||
authSessionMiddleware: mockAuthSessionMiddleware(userId),
|
|
||||||
})
|
|
||||||
return { app, sessionManager }
|
|
||||||
}
|
|
||||||
|
|
||||||
function putCredentials(app: Hono, sourceId: string, body: unknown) {
|
|
||||||
return app.request(`/api/sources/${sourceId}/credentials`, {
|
|
||||||
method: "PUT",
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function put(app: Hono, sourceId: string, body: unknown) {
|
function put(app: Hono, sourceId: string, body: unknown) {
|
||||||
return app.request(`/api/sources/${sourceId}`, {
|
return app.request(`/api/sources/${sourceId}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
@@ -743,123 +707,4 @@ describe("PUT /api/sources/:sourceId", () => {
|
|||||||
|
|
||||||
expect(res.status).toBe(204)
|
expect(res.status).toBe(204)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("returns 204 when credentials are included alongside config", async () => {
|
|
||||||
activeStore = createInMemoryStore()
|
|
||||||
const { app } = createAppWithEncryptor(
|
|
||||||
[createStubProvider("aelis.weather", weatherConfig)],
|
|
||||||
MOCK_USER_ID,
|
|
||||||
)
|
|
||||||
|
|
||||||
const res = await put(app, "aelis.weather", {
|
|
||||||
enabled: true,
|
|
||||||
config: { units: "metric" },
|
|
||||||
credentials: { apiKey: "secret123" },
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(res.status).toBe(204)
|
|
||||||
const row = activeStore.rows.get(`${MOCK_USER_ID}:aelis.weather`)
|
|
||||||
expect(row).toBeDefined()
|
|
||||||
expect(row!.enabled).toBe(true)
|
|
||||||
expect(row!.config).toEqual({ units: "metric" })
|
|
||||||
})
|
|
||||||
|
|
||||||
test("returns 503 when credentials are provided but no encryptor is configured", async () => {
|
|
||||||
activeStore = createInMemoryStore()
|
|
||||||
// createApp does NOT configure an encryptor
|
|
||||||
const { app } = createApp([createStubProvider("aelis.weather", weatherConfig)], MOCK_USER_ID)
|
|
||||||
|
|
||||||
const res = await put(app, "aelis.weather", {
|
|
||||||
enabled: true,
|
|
||||||
config: { units: "metric" },
|
|
||||||
credentials: { apiKey: "secret123" },
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(res.status).toBe(503)
|
|
||||||
const body = (await res.json()) as { error: string }
|
|
||||||
expect(body.error).toContain("not configured")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("PUT /api/sources/:sourceId/credentials", () => {
|
|
||||||
test("returns 401 without auth", async () => {
|
|
||||||
activeStore = createInMemoryStore()
|
|
||||||
const { app } = createAppWithEncryptor([createStubProvider("aelis.location")])
|
|
||||||
|
|
||||||
const res = await putCredentials(app, "aelis.location", { token: "x" })
|
|
||||||
|
|
||||||
expect(res.status).toBe(401)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("returns 404 for unknown source", async () => {
|
|
||||||
activeStore = createInMemoryStore()
|
|
||||||
const { app } = createAppWithEncryptor([createStubProvider("aelis.location")], MOCK_USER_ID)
|
|
||||||
|
|
||||||
const res = await putCredentials(app, "unknown.source", { token: "x" })
|
|
||||||
|
|
||||||
expect(res.status).toBe(404)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("returns 400 for invalid JSON", async () => {
|
|
||||||
activeStore = createInMemoryStore()
|
|
||||||
activeStore.seed(MOCK_USER_ID, "aelis.location")
|
|
||||||
const { app } = createAppWithEncryptor([createStubProvider("aelis.location")], MOCK_USER_ID)
|
|
||||||
|
|
||||||
const res = await app.request("/api/sources/aelis.location/credentials", {
|
|
||||||
method: "PUT",
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
body: "not-json",
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(res.status).toBe(400)
|
|
||||||
const body = (await res.json()) as { error: string }
|
|
||||||
expect(body.error).toBe("Invalid JSON")
|
|
||||||
})
|
|
||||||
|
|
||||||
test("returns 204 and persists credentials", async () => {
|
|
||||||
activeStore = createInMemoryStore()
|
|
||||||
activeStore.seed(MOCK_USER_ID, "aelis.location")
|
|
||||||
const { app } = createAppWithEncryptor([createStubProvider("aelis.location")], MOCK_USER_ID)
|
|
||||||
|
|
||||||
const res = await putCredentials(app, "aelis.location", { token: "secret" })
|
|
||||||
|
|
||||||
expect(res.status).toBe(204)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("returns 400 when provider throws InvalidSourceCredentialsError", async () => {
|
|
||||||
activeStore = createInMemoryStore()
|
|
||||||
activeStore.seed(MOCK_USER_ID, "test.creds")
|
|
||||||
let callCount = 0
|
|
||||||
const provider: FeedSourceProvider = {
|
|
||||||
sourceId: "test.creds",
|
|
||||||
async feedSourceForUser(_userId: string, _config: unknown, _credentials: unknown) {
|
|
||||||
callCount++
|
|
||||||
if (callCount > 1) {
|
|
||||||
throw new InvalidSourceCredentialsError("test.creds", "invalid token format")
|
|
||||||
}
|
|
||||||
return createStubSource("test.creds")
|
|
||||||
},
|
|
||||||
}
|
|
||||||
const { app, sessionManager } = createAppWithEncryptor([provider], MOCK_USER_ID)
|
|
||||||
|
|
||||||
await sessionManager.getOrCreate(MOCK_USER_ID)
|
|
||||||
|
|
||||||
const res = await putCredentials(app, "test.creds", { token: "bad" })
|
|
||||||
|
|
||||||
expect(res.status).toBe(400)
|
|
||||||
const body = (await res.json()) as { error: string }
|
|
||||||
expect(body.error).toContain("invalid token format")
|
|
||||||
})
|
|
||||||
|
|
||||||
test("returns 503 when credential encryption is not configured", async () => {
|
|
||||||
activeStore = createInMemoryStore()
|
|
||||||
activeStore.seed(MOCK_USER_ID, "aelis.location")
|
|
||||||
const { app } = createApp([createStubProvider("aelis.location")], MOCK_USER_ID)
|
|
||||||
|
|
||||||
const res = await putCredentials(app, "aelis.location", { token: "x" })
|
|
||||||
|
|
||||||
expect(res.status).toBe(503)
|
|
||||||
const body = (await res.json()) as { error: string }
|
|
||||||
expect(body.error).toContain("not configured")
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,12 +6,7 @@ import { createMiddleware } from "hono/factory"
|
|||||||
import type { AuthSessionMiddleware } from "../auth/session-middleware.ts"
|
import type { AuthSessionMiddleware } from "../auth/session-middleware.ts"
|
||||||
import type { UserSessionManager } from "../session/index.ts"
|
import type { UserSessionManager } from "../session/index.ts"
|
||||||
|
|
||||||
import {
|
import { InvalidSourceConfigError, SourceNotFoundError } from "./errors.ts"
|
||||||
CredentialStorageUnavailableError,
|
|
||||||
InvalidSourceConfigError,
|
|
||||||
InvalidSourceCredentialsError,
|
|
||||||
SourceNotFoundError,
|
|
||||||
} from "./errors.ts"
|
|
||||||
|
|
||||||
type Env = {
|
type Env = {
|
||||||
Variables: {
|
Variables: {
|
||||||
@@ -34,13 +29,11 @@ const ReplaceSourceConfigRequestBody = type({
|
|||||||
"+": "reject",
|
"+": "reject",
|
||||||
enabled: "boolean",
|
enabled: "boolean",
|
||||||
config: "unknown",
|
config: "unknown",
|
||||||
"credentials?": "unknown",
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const ReplaceSourceConfigNoConfigRequestBody = type({
|
const ReplaceSourceConfigNoConfigRequestBody = type({
|
||||||
"+": "reject",
|
"+": "reject",
|
||||||
enabled: "boolean",
|
enabled: "boolean",
|
||||||
"credentials?": "unknown",
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export function registerSourcesHttpHandlers(
|
export function registerSourcesHttpHandlers(
|
||||||
@@ -55,12 +48,6 @@ export function registerSourcesHttpHandlers(
|
|||||||
app.get("/api/sources/:sourceId", inject, authSessionMiddleware, handleGetSource)
|
app.get("/api/sources/:sourceId", inject, authSessionMiddleware, handleGetSource)
|
||||||
app.patch("/api/sources/:sourceId", inject, authSessionMiddleware, handleUpdateSource)
|
app.patch("/api/sources/:sourceId", inject, authSessionMiddleware, handleUpdateSource)
|
||||||
app.put("/api/sources/:sourceId", inject, authSessionMiddleware, handleReplaceSource)
|
app.put("/api/sources/:sourceId", inject, authSessionMiddleware, handleReplaceSource)
|
||||||
app.put(
|
|
||||||
"/api/sources/:sourceId/credentials",
|
|
||||||
inject,
|
|
||||||
authSessionMiddleware,
|
|
||||||
handleUpdateCredentials,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleGetSource(c: Context<Env>) {
|
async function handleGetSource(c: Context<Env>) {
|
||||||
@@ -163,15 +150,14 @@ async function handleReplaceSource(c: Context<Env>) {
|
|||||||
return c.json({ error: parsed.summary }, 400)
|
return c.json({ error: parsed.summary }, 400)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { enabled, credentials } = parsed
|
const { enabled } = parsed
|
||||||
const config = "config" in parsed ? parsed.config : undefined
|
const config = "config" in parsed ? parsed.config : undefined
|
||||||
const user = c.get("user")!
|
const user = c.get("user")!
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await sessionManager.saveSourceConfig(user.id, sourceId, {
|
await sessionManager.upsertSourceConfig(user.id, sourceId, {
|
||||||
enabled,
|
enabled,
|
||||||
config,
|
config,
|
||||||
credentials,
|
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof SourceNotFoundError) {
|
if (err instanceof SourceNotFoundError) {
|
||||||
@@ -180,49 +166,6 @@ async function handleReplaceSource(c: Context<Env>) {
|
|||||||
if (err instanceof InvalidSourceConfigError) {
|
if (err instanceof InvalidSourceConfigError) {
|
||||||
return c.json({ error: err.message }, 400)
|
return c.json({ error: err.message }, 400)
|
||||||
}
|
}
|
||||||
if (err instanceof CredentialStorageUnavailableError) {
|
|
||||||
return c.json({ error: err.message }, 503)
|
|
||||||
}
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.body(null, 204)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleUpdateCredentials(c: Context<Env>) {
|
|
||||||
const sourceId = c.req.param("sourceId")
|
|
||||||
if (!sourceId) {
|
|
||||||
return c.body(null, 404)
|
|
||||||
}
|
|
||||||
|
|
||||||
const sessionManager = c.get("sessionManager")
|
|
||||||
|
|
||||||
const provider = sessionManager.getProvider(sourceId)
|
|
||||||
if (!provider) {
|
|
||||||
return c.json({ error: `Source "${sourceId}" not found` }, 404)
|
|
||||||
}
|
|
||||||
|
|
||||||
let body: unknown
|
|
||||||
try {
|
|
||||||
body = await c.req.json()
|
|
||||||
} catch {
|
|
||||||
return c.json({ error: "Invalid JSON" }, 400)
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = c.get("user")!
|
|
||||||
|
|
||||||
try {
|
|
||||||
await sessionManager.updateSourceCredentials(user.id, sourceId, body)
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof SourceNotFoundError) {
|
|
||||||
return c.json({ error: err.message }, 404)
|
|
||||||
}
|
|
||||||
if (err instanceof InvalidSourceCredentialsError) {
|
|
||||||
return c.json({ error: err.message }, 400)
|
|
||||||
}
|
|
||||||
if (err instanceof CredentialStorageUnavailableError) {
|
|
||||||
return c.json({ error: err.message }, 503)
|
|
||||||
}
|
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,18 +26,6 @@ export function sources(db: Database, userId: string) {
|
|||||||
return rows[0]
|
return rows[0]
|
||||||
},
|
},
|
||||||
|
|
||||||
/** Like find(), but acquires a row lock to prevent concurrent modifications. Must be called inside a transaction. */
|
|
||||||
async findForUpdate(sourceId: string) {
|
|
||||||
const rows = await db
|
|
||||||
.select()
|
|
||||||
.from(userSources)
|
|
||||||
.where(and(eq(userSources.userId, userId), eq(userSources.sourceId, sourceId)))
|
|
||||||
.limit(1)
|
|
||||||
.for("update")
|
|
||||||
|
|
||||||
return rows[0]
|
|
||||||
},
|
|
||||||
|
|
||||||
/** Enables a source for the user. Throws if the source row doesn't exist. */
|
/** Enables a source for the user. Throws if the source row doesn't exist. */
|
||||||
async enableSource(sourceId: string) {
|
async enableSource(sourceId: string) {
|
||||||
const rows = await db
|
const rows = await db
|
||||||
|
|||||||
@@ -23,11 +23,7 @@ export class TflSourceProvider implements FeedSourceProvider {
|
|||||||
this.client = "client" in options ? options.client : undefined
|
this.client = "client" in options ? options.client : undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
async feedSourceForUser(
|
async feedSourceForUser(_userId: string, config: unknown): Promise<TflSource> {
|
||||||
_userId: string,
|
|
||||||
config: unknown,
|
|
||||||
_credentials: unknown,
|
|
||||||
): Promise<TflSource> {
|
|
||||||
const parsed = tflConfig(config)
|
const parsed = tflConfig(config)
|
||||||
if (parsed instanceof type.errors) {
|
if (parsed instanceof type.errors) {
|
||||||
throw new Error(`Invalid TFL config: ${parsed.summary}`)
|
throw new Error(`Invalid TFL config: ${parsed.summary}`)
|
||||||
|
|||||||
@@ -26,11 +26,7 @@ export class WeatherSourceProvider implements FeedSourceProvider {
|
|||||||
this.client = options.client
|
this.client = options.client
|
||||||
}
|
}
|
||||||
|
|
||||||
async feedSourceForUser(
|
async feedSourceForUser(_userId: string, config: unknown): Promise<WeatherSource> {
|
||||||
_userId: string,
|
|
||||||
config: unknown,
|
|
||||||
_credentials: unknown,
|
|
||||||
): Promise<WeatherSource> {
|
|
||||||
const parsed = weatherConfig(config)
|
const parsed = weatherConfig(config)
|
||||||
if (parsed instanceof type.errors) {
|
if (parsed instanceof type.errors) {
|
||||||
throw new Error(`Invalid weather config: ${parsed.summary}`)
|
throw new Error(`Invalid weather config: ${parsed.summary}`)
|
||||||
|
|||||||
@@ -55,112 +55,44 @@
|
|||||||
"fontFamily": "Inter",
|
"fontFamily": "Inter",
|
||||||
"fontDefinitions": [
|
"fontDefinitions": [
|
||||||
{ "path": "./assets/fonts/Inter_100Thin.ttf", "weight": 100 },
|
{ "path": "./assets/fonts/Inter_100Thin.ttf", "weight": 100 },
|
||||||
{
|
{ "path": "./assets/fonts/Inter_100Thin_Italic.ttf", "weight": 100, "style": "italic" },
|
||||||
"path": "./assets/fonts/Inter_100Thin_Italic.ttf",
|
|
||||||
"weight": 100,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/Inter_200ExtraLight.ttf", "weight": 200 },
|
{ "path": "./assets/fonts/Inter_200ExtraLight.ttf", "weight": 200 },
|
||||||
{
|
{ "path": "./assets/fonts/Inter_200ExtraLight_Italic.ttf", "weight": 200, "style": "italic" },
|
||||||
"path": "./assets/fonts/Inter_200ExtraLight_Italic.ttf",
|
|
||||||
"weight": 200,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/Inter_300Light.ttf", "weight": 300 },
|
{ "path": "./assets/fonts/Inter_300Light.ttf", "weight": 300 },
|
||||||
{
|
{ "path": "./assets/fonts/Inter_300Light_Italic.ttf", "weight": 300, "style": "italic" },
|
||||||
"path": "./assets/fonts/Inter_300Light_Italic.ttf",
|
|
||||||
"weight": 300,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/Inter_400Regular.ttf", "weight": 400 },
|
{ "path": "./assets/fonts/Inter_400Regular.ttf", "weight": 400 },
|
||||||
{
|
{ "path": "./assets/fonts/Inter_400Regular_Italic.ttf", "weight": 400, "style": "italic" },
|
||||||
"path": "./assets/fonts/Inter_400Regular_Italic.ttf",
|
|
||||||
"weight": 400,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/Inter_500Medium.ttf", "weight": 500 },
|
{ "path": "./assets/fonts/Inter_500Medium.ttf", "weight": 500 },
|
||||||
{
|
{ "path": "./assets/fonts/Inter_500Medium_Italic.ttf", "weight": 500, "style": "italic" },
|
||||||
"path": "./assets/fonts/Inter_500Medium_Italic.ttf",
|
|
||||||
"weight": 500,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/Inter_600SemiBold.ttf", "weight": 600 },
|
{ "path": "./assets/fonts/Inter_600SemiBold.ttf", "weight": 600 },
|
||||||
{
|
{ "path": "./assets/fonts/Inter_600SemiBold_Italic.ttf", "weight": 600, "style": "italic" },
|
||||||
"path": "./assets/fonts/Inter_600SemiBold_Italic.ttf",
|
|
||||||
"weight": 600,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/Inter_700Bold.ttf", "weight": 700 },
|
{ "path": "./assets/fonts/Inter_700Bold.ttf", "weight": 700 },
|
||||||
{
|
{ "path": "./assets/fonts/Inter_700Bold_Italic.ttf", "weight": 700, "style": "italic" },
|
||||||
"path": "./assets/fonts/Inter_700Bold_Italic.ttf",
|
|
||||||
"weight": 700,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/Inter_800ExtraBold.ttf", "weight": 800 },
|
{ "path": "./assets/fonts/Inter_800ExtraBold.ttf", "weight": 800 },
|
||||||
{
|
{ "path": "./assets/fonts/Inter_800ExtraBold_Italic.ttf", "weight": 800, "style": "italic" },
|
||||||
"path": "./assets/fonts/Inter_800ExtraBold_Italic.ttf",
|
|
||||||
"weight": 800,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/Inter_900Black.ttf", "weight": 900 },
|
{ "path": "./assets/fonts/Inter_900Black.ttf", "weight": 900 },
|
||||||
{
|
{ "path": "./assets/fonts/Inter_900Black_Italic.ttf", "weight": 900, "style": "italic" }
|
||||||
"path": "./assets/fonts/Inter_900Black_Italic.ttf",
|
|
||||||
"weight": 900,
|
|
||||||
"style": "italic"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fontFamily": "Source Serif 4",
|
"fontFamily": "Source Serif 4",
|
||||||
"fontDefinitions": [
|
"fontDefinitions": [
|
||||||
{ "path": "./assets/fonts/SourceSerif4_200ExtraLight.ttf", "weight": 200 },
|
{ "path": "./assets/fonts/SourceSerif4_200ExtraLight.ttf", "weight": 200 },
|
||||||
{
|
{ "path": "./assets/fonts/SourceSerif4_200ExtraLight_Italic.ttf", "weight": 200, "style": "italic" },
|
||||||
"path": "./assets/fonts/SourceSerif4_200ExtraLight_Italic.ttf",
|
|
||||||
"weight": 200,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/SourceSerif4_300Light.ttf", "weight": 300 },
|
{ "path": "./assets/fonts/SourceSerif4_300Light.ttf", "weight": 300 },
|
||||||
{
|
{ "path": "./assets/fonts/SourceSerif4_300Light_Italic.ttf", "weight": 300, "style": "italic" },
|
||||||
"path": "./assets/fonts/SourceSerif4_300Light_Italic.ttf",
|
|
||||||
"weight": 300,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/SourceSerif4_400Regular.ttf", "weight": 400 },
|
{ "path": "./assets/fonts/SourceSerif4_400Regular.ttf", "weight": 400 },
|
||||||
{
|
{ "path": "./assets/fonts/SourceSerif4_400Regular_Italic.ttf", "weight": 400, "style": "italic" },
|
||||||
"path": "./assets/fonts/SourceSerif4_400Regular_Italic.ttf",
|
|
||||||
"weight": 400,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/SourceSerif4_500Medium.ttf", "weight": 500 },
|
{ "path": "./assets/fonts/SourceSerif4_500Medium.ttf", "weight": 500 },
|
||||||
{
|
{ "path": "./assets/fonts/SourceSerif4_500Medium_Italic.ttf", "weight": 500, "style": "italic" },
|
||||||
"path": "./assets/fonts/SourceSerif4_500Medium_Italic.ttf",
|
|
||||||
"weight": 500,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/SourceSerif4_600SemiBold.ttf", "weight": 600 },
|
{ "path": "./assets/fonts/SourceSerif4_600SemiBold.ttf", "weight": 600 },
|
||||||
{
|
{ "path": "./assets/fonts/SourceSerif4_600SemiBold_Italic.ttf", "weight": 600, "style": "italic" },
|
||||||
"path": "./assets/fonts/SourceSerif4_600SemiBold_Italic.ttf",
|
|
||||||
"weight": 600,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/SourceSerif4_700Bold.ttf", "weight": 700 },
|
{ "path": "./assets/fonts/SourceSerif4_700Bold.ttf", "weight": 700 },
|
||||||
{
|
{ "path": "./assets/fonts/SourceSerif4_700Bold_Italic.ttf", "weight": 700, "style": "italic" },
|
||||||
"path": "./assets/fonts/SourceSerif4_700Bold_Italic.ttf",
|
|
||||||
"weight": 700,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/SourceSerif4_800ExtraBold.ttf", "weight": 800 },
|
{ "path": "./assets/fonts/SourceSerif4_800ExtraBold.ttf", "weight": 800 },
|
||||||
{
|
{ "path": "./assets/fonts/SourceSerif4_800ExtraBold_Italic.ttf", "weight": 800, "style": "italic" },
|
||||||
"path": "./assets/fonts/SourceSerif4_800ExtraBold_Italic.ttf",
|
|
||||||
"weight": 800,
|
|
||||||
"style": "italic"
|
|
||||||
},
|
|
||||||
{ "path": "./assets/fonts/SourceSerif4_900Black.ttf", "weight": 900 },
|
{ "path": "./assets/fonts/SourceSerif4_900Black.ttf", "weight": 900 },
|
||||||
{
|
{ "path": "./assets/fonts/SourceSerif4_900Black_Italic.ttf", "weight": 900, "style": "italic" }
|
||||||
"path": "./assets/fonts/SourceSerif4_900Black_Italic.ttf",
|
|
||||||
"weight": 900,
|
|
||||||
"style": "italic"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -55,6 +55,6 @@
|
|||||||
"eas-cli": "^18.0.1",
|
"eas-cli": "^18.0.1",
|
||||||
"eslint": "^9.25.0",
|
"eslint": "^9.25.0",
|
||||||
"eslint-config-expo": "~10.0.0",
|
"eslint-config-expo": "~10.0.0",
|
||||||
"typescript": "^6"
|
"typescript": "~5.9.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ export class ApiClient {
|
|||||||
(prevInit, middleware) => middleware(url, prevInit),
|
(prevInit, middleware) => middleware(url, prevInit),
|
||||||
init,
|
init,
|
||||||
)
|
)
|
||||||
return fetch(this.baseUrl ? new URL(url.toString(), this.baseUrl) : url, finalInit).then(
|
return fetch(this.baseUrl ? new URL(url.toString(), this.baseUrl) : url, finalInit).then((res) =>
|
||||||
(res) => Promise.all([Promise.resolve(res), res.json()]),
|
Promise.all([Promise.resolve(res), res.json()]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ import { useEffect } from "react"
|
|||||||
import { ScrollView, View } from "react-native"
|
import { ScrollView, View } from "react-native"
|
||||||
import tw from "twrnc"
|
import tw from "twrnc"
|
||||||
|
|
||||||
import { type Showcase } from "@/components/showcase"
|
|
||||||
import { buttonShowcase } from "@/components/ui/button.showcase"
|
import { buttonShowcase } from "@/components/ui/button.showcase"
|
||||||
import { feedCardShowcase } from "@/components/ui/feed-card.showcase"
|
import { feedCardShowcase } from "@/components/ui/feed-card.showcase"
|
||||||
import { monospaceTextShowcase } from "@/components/ui/monospace-text.showcase"
|
import { monospaceTextShowcase } from "@/components/ui/monospace-text.showcase"
|
||||||
import { SansSerifText } from "@/components/ui/sans-serif-text"
|
|
||||||
import { sansSerifTextShowcase } from "@/components/ui/sans-serif-text.showcase"
|
import { sansSerifTextShowcase } from "@/components/ui/sans-serif-text.showcase"
|
||||||
import { serifTextShowcase } from "@/components/ui/serif-text.showcase"
|
import { serifTextShowcase } from "@/components/ui/serif-text.showcase"
|
||||||
|
import { type Showcase } from "@/components/showcase"
|
||||||
|
import { SansSerifText } from "@/components/ui/sans-serif-text"
|
||||||
|
|
||||||
const showcases: Record<string, Showcase> = {
|
const showcases: Record<string, Showcase> = {
|
||||||
button: buttonShowcase,
|
button: buttonShowcase,
|
||||||
@@ -41,10 +41,7 @@ export default function ComponentDetailScreen() {
|
|||||||
const ShowcaseComponent = showcase.component
|
const ShowcaseComponent = showcase.component
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView
|
<ScrollView style={tw`bg-stone-100 dark:bg-stone-900 flex-1`} contentContainerStyle={tw`px-5 pb-10 pt-4 gap-6`}>
|
||||||
style={tw`bg-stone-100 dark:bg-stone-900 flex-1`}
|
|
||||||
contentContainerStyle={tw`px-5 pb-10 pt-4 gap-6`}
|
|
||||||
>
|
|
||||||
<ShowcaseComponent />
|
<ShowcaseComponent />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,9 +15,7 @@ const components = [
|
|||||||
export default function ComponentsScreen() {
|
export default function ComponentsScreen() {
|
||||||
return (
|
return (
|
||||||
<View style={tw`flex-1`}>
|
<View style={tw`flex-1`}>
|
||||||
<View
|
<View style={tw`mx-4 mt-4 rounded-xl border border-stone-200 dark:border-stone-800 overflow-hidden`}>
|
||||||
style={tw`mx-4 mt-4 rounded-xl border border-stone-200 dark:border-stone-800 overflow-hidden`}
|
|
||||||
>
|
|
||||||
<FlatList
|
<FlatList
|
||||||
data={components}
|
data={components}
|
||||||
keyExtractor={(item) => item.name}
|
keyExtractor={(item) => item.name}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { View } from "react-native"
|
import { View } from "react-native"
|
||||||
import tw from "twrnc"
|
import tw from "twrnc"
|
||||||
|
|
||||||
import { type Showcase, Section } from "../showcase"
|
|
||||||
import { Button } from "./button"
|
import { Button } from "./button"
|
||||||
|
import { type Showcase, Section } from "../showcase"
|
||||||
|
|
||||||
function ButtonShowcase() {
|
function ButtonShowcase() {
|
||||||
return (
|
return (
|
||||||
@@ -11,7 +11,11 @@ function ButtonShowcase() {
|
|||||||
<Button style={tw`self-start`} label="Press me" />
|
<Button style={tw`self-start`} label="Press me" />
|
||||||
</Section>
|
</Section>
|
||||||
<Section title="Leading icon">
|
<Section title="Leading icon">
|
||||||
<Button style={tw`self-start`} label="Add item" leadingIcon={<Button.Icon name="plus" />} />
|
<Button
|
||||||
|
style={tw`self-start`}
|
||||||
|
label="Add item"
|
||||||
|
leadingIcon={<Button.Icon name="plus" />}
|
||||||
|
/>
|
||||||
</Section>
|
</Section>
|
||||||
<Section title="Trailing icon">
|
<Section title="Trailing icon">
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -23,11 +23,7 @@ type ButtonProps = Omit<PressableProps, "children"> & {
|
|||||||
export function Button({ style, label, leadingIcon, trailingIcon, ...props }: ButtonProps) {
|
export function Button({ style, label, leadingIcon, trailingIcon, ...props }: ButtonProps) {
|
||||||
const hasIcons = leadingIcon != null || trailingIcon != null
|
const hasIcons = leadingIcon != null || trailingIcon != null
|
||||||
|
|
||||||
const textElement = (
|
const textElement = <SansSerifText style={tw`text-stone-100 dark:text-stone-200 font-medium`}>{label}</SansSerifText>
|
||||||
<SansSerifText style={tw`text-stone-100 dark:text-stone-200 font-medium`}>
|
|
||||||
{label}
|
|
||||||
</SansSerifText>
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Pressable style={[tw`rounded-full bg-teal-600 px-4 py-3 w-fit`, style]} {...props}>
|
<Pressable style={[tw`rounded-full bg-teal-600 px-4 py-3 w-fit`, style]} {...props}>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { View } from "react-native"
|
import { View } from "react-native"
|
||||||
import tw from "twrnc"
|
import tw from "twrnc"
|
||||||
|
|
||||||
import { type Showcase, Section } from "../showcase"
|
|
||||||
import { Button } from "./button"
|
import { Button } from "./button"
|
||||||
import { FeedCard } from "./feed-card"
|
import { FeedCard } from "./feed-card"
|
||||||
import { SansSerifText } from "./sans-serif-text"
|
import { SansSerifText } from "./sans-serif-text"
|
||||||
import { SerifText } from "./serif-text"
|
import { SerifText } from "./serif-text"
|
||||||
|
import { type Showcase, Section } from "../showcase"
|
||||||
|
|
||||||
function FeedCardShowcase() {
|
function FeedCardShowcase() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -2,10 +2,5 @@ import { View, type ViewProps } from "react-native"
|
|||||||
import tw from "twrnc"
|
import tw from "twrnc"
|
||||||
|
|
||||||
export function FeedCard({ style, ...props }: ViewProps) {
|
export function FeedCard({ style, ...props }: ViewProps) {
|
||||||
return (
|
return <View style={[tw`border border-stone-200 dark:border-stone-800 rounded-lg`, style]} {...props} />
|
||||||
<View
|
|
||||||
style={[tw`border border-stone-200 dark:border-stone-800 rounded-lg`, style]}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { View } from "react-native"
|
import { View } from "react-native"
|
||||||
import tw from "twrnc"
|
import tw from "twrnc"
|
||||||
|
|
||||||
import { type Showcase, Section } from "../showcase"
|
|
||||||
import { MonospaceText } from "./monospace-text"
|
import { MonospaceText } from "./monospace-text"
|
||||||
|
import { type Showcase, Section } from "../showcase"
|
||||||
|
|
||||||
function MonospaceTextShowcase() {
|
function MonospaceTextShowcase() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,10 +3,7 @@ import tw from "twrnc"
|
|||||||
|
|
||||||
export function MonospaceText({ children, style, ...props }: TextProps) {
|
export function MonospaceText({ children, style, ...props }: TextProps) {
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text style={[tw`text-stone-800 dark:text-stone-200`, { fontFamily: "Menlo" }, style]} {...props}>
|
||||||
style={[tw`text-stone-800 dark:text-stone-200`, { fontFamily: "Menlo" }, style]}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { View } from "react-native"
|
import { View } from "react-native"
|
||||||
import tw from "twrnc"
|
import tw from "twrnc"
|
||||||
|
|
||||||
import { type Showcase, Section } from "../showcase"
|
|
||||||
import { SansSerifText } from "./sans-serif-text"
|
import { SansSerifText } from "./sans-serif-text"
|
||||||
|
import { type Showcase, Section } from "../showcase"
|
||||||
|
|
||||||
function SansSerifTextShowcase() {
|
function SansSerifTextShowcase() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,10 +3,7 @@ import tw from "twrnc"
|
|||||||
|
|
||||||
export function SansSerifText({ children, style, ...props }: TextProps) {
|
export function SansSerifText({ children, style, ...props }: TextProps) {
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text style={[tw`text-stone-800 dark:text-stone-200`, { fontFamily: "Inter" }, style]} {...props}>
|
||||||
style={[tw`text-stone-800 dark:text-stone-200`, { fontFamily: "Inter" }, style]}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { View } from "react-native"
|
import { View } from "react-native"
|
||||||
import tw from "twrnc"
|
import tw from "twrnc"
|
||||||
|
|
||||||
import { type Showcase, Section } from "../showcase"
|
|
||||||
import { SerifText } from "./serif-text"
|
import { SerifText } from "./serif-text"
|
||||||
|
import { type Showcase, Section } from "../showcase"
|
||||||
|
|
||||||
function SerifTextShowcase() {
|
function SerifTextShowcase() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,10 +3,7 @@ import tw from "twrnc"
|
|||||||
|
|
||||||
export function SerifText({ children, style, ...props }: TextProps) {
|
export function SerifText({ children, style, ...props }: TextProps) {
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text style={[tw`text-stone-800 dark:text-stone-200`, { fontFamily: "Source Serif 4" }, style]} {...props}>
|
||||||
style={[tw`text-stone-800 dark:text-stone-200`, { fontFamily: "Source Serif 4" }, style]}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ export const catalog = defineCatalog(schema, {
|
|||||||
style: z.string().nullable(),
|
style: z.string().nullable(),
|
||||||
}),
|
}),
|
||||||
slots: ["default"],
|
slots: ["default"],
|
||||||
description:
|
description: "Bordered card container for feed content. The style prop accepts a twrnc class string.",
|
||||||
"Bordered card container for feed content. The style prop accepts a twrnc class string.",
|
|
||||||
example: { style: "p-4 gap-2" },
|
example: { style: "p-4 gap-2" },
|
||||||
},
|
},
|
||||||
SansSerifText: {
|
SansSerifText: {
|
||||||
|
|||||||
@@ -14,20 +14,12 @@ type ButtonIconName = React.ComponentProps<typeof Button.Icon>["name"]
|
|||||||
|
|
||||||
export const { registry } = defineRegistry(catalog, {
|
export const { registry } = defineRegistry(catalog, {
|
||||||
components: {
|
components: {
|
||||||
View: ({ props, children }) => (
|
View: ({ props, children }) => <View style={props.style ? tw`${props.style}` : undefined}>{children}</View>,
|
||||||
<View style={props.style ? tw`${props.style}` : undefined}>{children}</View>
|
|
||||||
),
|
|
||||||
Button: ({ props, emit }) => (
|
Button: ({ props, emit }) => (
|
||||||
<Button
|
<Button
|
||||||
label={props.label}
|
label={props.label}
|
||||||
leadingIcon={
|
leadingIcon={props.leadingIcon ? <Button.Icon name={props.leadingIcon as ButtonIconName} /> : undefined}
|
||||||
props.leadingIcon ? <Button.Icon name={props.leadingIcon as ButtonIconName} /> : undefined
|
trailingIcon={props.trailingIcon ? <Button.Icon name={props.trailingIcon as ButtonIconName} /> : undefined}
|
||||||
}
|
|
||||||
trailingIcon={
|
|
||||||
props.trailingIcon ? (
|
|
||||||
<Button.Icon name={props.trailingIcon as ButtonIconName} />
|
|
||||||
) : undefined
|
|
||||||
}
|
|
||||||
onPress={() => emit("press")}
|
onPress={() => emit("press")}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@@ -35,17 +27,13 @@ export const { registry } = defineRegistry(catalog, {
|
|||||||
<FeedCard style={props.style ? tw`${props.style}` : undefined}>{children}</FeedCard>
|
<FeedCard style={props.style ? tw`${props.style}` : undefined}>{children}</FeedCard>
|
||||||
),
|
),
|
||||||
SansSerifText: ({ props }) => (
|
SansSerifText: ({ props }) => (
|
||||||
<SansSerifText style={props.style ? tw`${props.style}` : undefined}>
|
<SansSerifText style={props.style ? tw`${props.style}` : undefined}>{props.text}</SansSerifText>
|
||||||
{props.text}
|
|
||||||
</SansSerifText>
|
|
||||||
),
|
),
|
||||||
SerifText: ({ props }) => (
|
SerifText: ({ props }) => (
|
||||||
<SerifText style={props.style ? tw`${props.style}` : undefined}>{props.text}</SerifText>
|
<SerifText style={props.style ? tw`${props.style}` : undefined}>{props.text}</SerifText>
|
||||||
),
|
),
|
||||||
MonospaceText: ({ props }) => (
|
MonospaceText: ({ props }) => (
|
||||||
<MonospaceText style={props.style ? tw`${props.style}` : undefined}>
|
<MonospaceText style={props.style ? tw`${props.style}` : undefined}>{props.text}</MonospaceText>
|
||||||
{props.text}
|
|
||||||
</MonospaceText>
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,131 +1 @@
|
|||||||
{
|
{"fr":60,"h":400,"ip":0,"layers":[{"ind":3,"ty":4,"parent":2,"ks":{},"ip":0,"op":7,"st":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","p":{"a":0,"k":[160,53]},"r":{"a":0,"k":0},"s":{"a":0,"k":[336,122]}},{"ty":"fl","c":{"a":0,"k":[0,0,0,0]},"o":{"a":0,"k":0}},{"ty":"tr","o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"el","p":{"a":0,"k":[160,53]},"s":{"a":0,"k":[320,106]}},{"ty":"st","c":{"a":0,"k":[0.906,0.898,0.894]},"lc":1,"lj":1,"ml":10,"o":{"a":0,"k":100},"w":{"a":0,"k":16}},{"ty":"tr","o":{"a":0,"k":100}}]}]},{"ind":2,"ty":3,"parent":1,"ks":{"a":{"a":0,"k":[160,53]},"p":{"a":0,"k":[200.5,200]},"r":{"a":1,"k":[{"t":0,"s":[-30],"i":{"x":0,"y":1},"o":{"x":0.5,"y":0}},{"t":6,"s":[-10],"h":1}]}},"ip":0,"op":7,"st":0},{"ind":5,"ty":4,"parent":4,"ks":{},"ip":0,"op":7,"st":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","p":{"a":0,"k":[160,53]},"r":{"a":0,"k":0},"s":{"a":0,"k":[336,122]}},{"ty":"fl","c":{"a":0,"k":[0,0,0,0]},"o":{"a":0,"k":0}},{"ty":"tr","o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"el","p":{"a":0,"k":[160,53]},"s":{"a":0,"k":[320,106]}},{"ty":"st","c":{"a":0,"k":[0.906,0.898,0.894]},"lc":1,"lj":1,"ml":10,"o":{"a":0,"k":100},"w":{"a":0,"k":16}},{"ty":"tr","o":{"a":0,"k":100}}]}]},{"ind":4,"ty":3,"parent":1,"ks":{"a":{"a":0,"k":[160,53]},"p":{"a":0,"k":[200.594,200.176]},"r":{"a":1,"k":[{"t":0,"s":[30],"i":{"x":0,"y":1},"o":{"x":0.5,"y":0}},{"t":6,"s":[10],"h":1}]}},"ip":0,"op":7,"st":0},{"ind":1,"ty":3,"parent":0,"ks":{},"ip":0,"op":7,"st":0},{"ind":0,"ty":3,"ks":{},"ip":0,"op":7,"st":0}],"meta":{"g":"https://jitter.video"},"op":6,"v":"5.7.4","w":400}
|
||||||
"fr": 60,
|
|
||||||
"h": 400,
|
|
||||||
"ip": 0,
|
|
||||||
"layers": [
|
|
||||||
{
|
|
||||||
"ind": 3,
|
|
||||||
"ty": 4,
|
|
||||||
"parent": 2,
|
|
||||||
"ks": {},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 7,
|
|
||||||
"st": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "rc",
|
|
||||||
"p": { "a": 0, "k": [160, 53] },
|
|
||||||
"r": { "a": 0, "k": 0 },
|
|
||||||
"s": { "a": 0, "k": [336, 122] }
|
|
||||||
},
|
|
||||||
{ "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } },
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{ "ty": "el", "p": { "a": 0, "k": [160, 53] }, "s": { "a": 0, "k": [320, 106] } },
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": { "a": 0, "k": [0.906, 0.898, 0.894] },
|
|
||||||
"lc": 1,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 10,
|
|
||||||
"o": { "a": 0, "k": 100 },
|
|
||||||
"w": { "a": 0, "k": 16 }
|
|
||||||
},
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 2,
|
|
||||||
"ty": 3,
|
|
||||||
"parent": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": { "a": 0, "k": [160, 53] },
|
|
||||||
"p": { "a": 0, "k": [200.5, 200] },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{ "t": 0, "s": [-30], "i": { "x": 0, "y": 1 }, "o": { "x": 0.5, "y": 0 } },
|
|
||||||
{ "t": 6, "s": [-10], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 7,
|
|
||||||
"st": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 5,
|
|
||||||
"ty": 4,
|
|
||||||
"parent": 4,
|
|
||||||
"ks": {},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 7,
|
|
||||||
"st": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "rc",
|
|
||||||
"p": { "a": 0, "k": [160, 53] },
|
|
||||||
"r": { "a": 0, "k": 0 },
|
|
||||||
"s": { "a": 0, "k": [336, 122] }
|
|
||||||
},
|
|
||||||
{ "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } },
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{ "ty": "el", "p": { "a": 0, "k": [160, 53] }, "s": { "a": 0, "k": [320, 106] } },
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": { "a": 0, "k": [0.906, 0.898, 0.894] },
|
|
||||||
"lc": 1,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 10,
|
|
||||||
"o": { "a": 0, "k": 100 },
|
|
||||||
"w": { "a": 0, "k": 16 }
|
|
||||||
},
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 4,
|
|
||||||
"ty": 3,
|
|
||||||
"parent": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": { "a": 0, "k": [160, 53] },
|
|
||||||
"p": { "a": 0, "k": [200.594, 200.176] },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{ "t": 0, "s": [30], "i": { "x": 0, "y": 1 }, "o": { "x": 0.5, "y": 0 } },
|
|
||||||
{ "t": 6, "s": [10], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 7,
|
|
||||||
"st": 0
|
|
||||||
},
|
|
||||||
{ "ind": 1, "ty": 3, "parent": 0, "ks": {}, "ip": 0, "op": 7, "st": 0 },
|
|
||||||
{ "ind": 0, "ty": 3, "ks": {}, "ip": 0, "op": 7, "st": 0 }
|
|
||||||
],
|
|
||||||
"meta": { "g": "https://jitter.video" },
|
|
||||||
"op": 6,
|
|
||||||
"v": "5.7.4",
|
|
||||||
"w": 400
|
|
||||||
}
|
|
||||||
@@ -1,131 +1 @@
|
|||||||
{
|
{"fr":60,"h":400,"ip":0,"layers":[{"ind":3,"ty":4,"parent":2,"ks":{},"ip":0,"op":7,"st":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","p":{"a":0,"k":[160,53]},"r":{"a":0,"k":0},"s":{"a":0,"k":[336,122]}},{"ty":"fl","c":{"a":0,"k":[0,0,0,0]},"o":{"a":0,"k":0}},{"ty":"tr","o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"el","p":{"a":0,"k":[160,53]},"s":{"a":0,"k":[320,106]}},{"ty":"st","c":{"a":0,"k":[0.11,0.098,0.09]},"lc":1,"lj":1,"ml":10,"o":{"a":0,"k":100},"w":{"a":0,"k":16}},{"ty":"tr","o":{"a":0,"k":100}}]}]},{"ind":2,"ty":3,"parent":1,"ks":{"a":{"a":0,"k":[160,53]},"p":{"a":0,"k":[200.5,200]},"r":{"a":1,"k":[{"t":0,"s":[-30],"i":{"x":0,"y":1},"o":{"x":0.5,"y":0}},{"t":6,"s":[-10],"h":1}]}},"ip":0,"op":7,"st":0},{"ind":5,"ty":4,"parent":4,"ks":{},"ip":0,"op":7,"st":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","p":{"a":0,"k":[160,53]},"r":{"a":0,"k":0},"s":{"a":0,"k":[336,122]}},{"ty":"fl","c":{"a":0,"k":[0,0,0,0]},"o":{"a":0,"k":0}},{"ty":"tr","o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"el","p":{"a":0,"k":[160,53]},"s":{"a":0,"k":[320,106]}},{"ty":"st","c":{"a":0,"k":[0.11,0.098,0.09]},"lc":1,"lj":1,"ml":10,"o":{"a":0,"k":100},"w":{"a":0,"k":16}},{"ty":"tr","o":{"a":0,"k":100}}]}]},{"ind":4,"ty":3,"parent":1,"ks":{"a":{"a":0,"k":[160,53]},"p":{"a":0,"k":[200.594,200.176]},"r":{"a":1,"k":[{"t":0,"s":[30],"i":{"x":0,"y":1},"o":{"x":0.5,"y":0}},{"t":6,"s":[10],"h":1}]}},"ip":0,"op":7,"st":0},{"ind":1,"ty":3,"parent":0,"ks":{},"ip":0,"op":7,"st":0},{"ind":0,"ty":3,"ks":{},"ip":0,"op":7,"st":0}],"meta":{"g":"https://jitter.video"},"op":6,"v":"5.7.4","w":400}
|
||||||
"fr": 60,
|
|
||||||
"h": 400,
|
|
||||||
"ip": 0,
|
|
||||||
"layers": [
|
|
||||||
{
|
|
||||||
"ind": 3,
|
|
||||||
"ty": 4,
|
|
||||||
"parent": 2,
|
|
||||||
"ks": {},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 7,
|
|
||||||
"st": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "rc",
|
|
||||||
"p": { "a": 0, "k": [160, 53] },
|
|
||||||
"r": { "a": 0, "k": 0 },
|
|
||||||
"s": { "a": 0, "k": [336, 122] }
|
|
||||||
},
|
|
||||||
{ "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } },
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{ "ty": "el", "p": { "a": 0, "k": [160, 53] }, "s": { "a": 0, "k": [320, 106] } },
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": { "a": 0, "k": [0.11, 0.098, 0.09] },
|
|
||||||
"lc": 1,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 10,
|
|
||||||
"o": { "a": 0, "k": 100 },
|
|
||||||
"w": { "a": 0, "k": 16 }
|
|
||||||
},
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 2,
|
|
||||||
"ty": 3,
|
|
||||||
"parent": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": { "a": 0, "k": [160, 53] },
|
|
||||||
"p": { "a": 0, "k": [200.5, 200] },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{ "t": 0, "s": [-30], "i": { "x": 0, "y": 1 }, "o": { "x": 0.5, "y": 0 } },
|
|
||||||
{ "t": 6, "s": [-10], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 7,
|
|
||||||
"st": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 5,
|
|
||||||
"ty": 4,
|
|
||||||
"parent": 4,
|
|
||||||
"ks": {},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 7,
|
|
||||||
"st": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "rc",
|
|
||||||
"p": { "a": 0, "k": [160, 53] },
|
|
||||||
"r": { "a": 0, "k": 0 },
|
|
||||||
"s": { "a": 0, "k": [336, 122] }
|
|
||||||
},
|
|
||||||
{ "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } },
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{ "ty": "el", "p": { "a": 0, "k": [160, 53] }, "s": { "a": 0, "k": [320, 106] } },
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": { "a": 0, "k": [0.11, 0.098, 0.09] },
|
|
||||||
"lc": 1,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 10,
|
|
||||||
"o": { "a": 0, "k": 100 },
|
|
||||||
"w": { "a": 0, "k": 16 }
|
|
||||||
},
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 4,
|
|
||||||
"ty": 3,
|
|
||||||
"parent": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": { "a": 0, "k": [160, 53] },
|
|
||||||
"p": { "a": 0, "k": [200.594, 200.176] },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{ "t": 0, "s": [30], "i": { "x": 0, "y": 1 }, "o": { "x": 0.5, "y": 0 } },
|
|
||||||
{ "t": 6, "s": [10], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 7,
|
|
||||||
"st": 0
|
|
||||||
},
|
|
||||||
{ "ind": 1, "ty": 3, "parent": 0, "ks": {}, "ip": 0, "op": 7, "st": 0 },
|
|
||||||
{ "ind": 0, "ty": 3, "ks": {}, "ip": 0, "op": 7, "st": 0 }
|
|
||||||
],
|
|
||||||
"meta": { "g": "https://jitter.video" },
|
|
||||||
"op": 6,
|
|
||||||
"v": "5.7.4",
|
|
||||||
"w": 400
|
|
||||||
}
|
|
||||||
@@ -1,281 +1 @@
|
|||||||
{
|
{"fr":60,"h":400,"ip":0,"layers":[{"ind":3,"ty":4,"parent":2,"ks":{},"ip":0,"op":61,"st":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","p":{"a":0,"k":[160,26.75]},"r":{"a":0,"k":0},"s":{"a":0,"k":[336,174.5]}},{"ty":"fl","c":{"a":0,"k":[0,0,0,0]},"o":{"a":0,"k":0}},{"ty":"tr","o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"el","p":{"a":1,"k":[{"t":0,"s":[160,0.5],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":8.4,"s":[160,0.5],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":30,"s":[160,53],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":37.8,"s":[160,53],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":60,"s":[160,0.5],"h":1}]},"s":{"a":1,"k":[{"t":0,"s":[320,1],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":8.4,"s":[320,1],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":30,"s":[320,106],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":37.8,"s":[320,106],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":60,"s":[320,1],"h":1}]}},{"ty":"st","c":{"a":0,"k":[0.906,0.898,0.894]},"lc":1,"lj":1,"ml":10,"o":{"a":0,"k":100},"w":{"a":0,"k":16}},{"ty":"tr","o":{"a":0,"k":100}}]}]},{"ind":2,"ty":3,"parent":1,"ks":{"a":{"a":1,"k":[{"t":0,"s":[160,0.5],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":8.4,"s":[160,0.5],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":30,"s":[160,53],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":37.8,"s":[160,53],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":60,"s":[160,0.5],"h":1}]},"p":{"a":0,"k":[200,200.014]},"r":{"a":1,"k":[{"t":0,"s":[-90],"h":1},{"t":8.4,"s":[-90],"i":{"x":0,"y":1},"o":{"x":0.5,"y":0}},{"t":30,"s":[0],"h":1},{"t":37.8,"s":[0],"i":{"x":0,"y":1},"o":{"x":0.5,"y":0}},{"t":60,"s":[90],"h":1}]}},"ip":0,"op":61,"st":0},{"ind":5,"ty":4,"parent":4,"ks":{},"ip":0,"op":61,"st":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","p":{"a":0,"k":[160,26.75]},"r":{"a":0,"k":0},"s":{"a":0,"k":[336,174.5]}},{"ty":"fl","c":{"a":0,"k":[0,0,0,0]},"o":{"a":0,"k":0}},{"ty":"tr","o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"el","p":{"a":1,"k":[{"t":0,"s":[160,0.5],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":30,"s":[160,53],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":60,"s":[160,0.5],"h":1}]},"s":{"a":1,"k":[{"t":0,"s":[320,1],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":30,"s":[320,106],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":60,"s":[320,1],"h":1}]}},{"ty":"st","c":{"a":0,"k":[0.906,0.898,0.894]},"lc":1,"lj":1,"ml":10,"o":{"a":0,"k":100},"w":{"a":0,"k":16}},{"ty":"tr","o":{"a":0,"k":100}}]}]},{"ind":4,"ty":3,"parent":1,"ks":{"a":{"a":1,"k":[{"t":0,"s":[160,0.5],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":30,"s":[160,53],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":60,"s":[160,0.5],"h":1}]},"p":{"a":0,"k":[200.094,200.19]},"r":{"a":1,"k":[{"t":0,"s":[-90],"i":{"x":0,"y":1},"o":{"x":0.5,"y":0}},{"t":30,"s":[0],"i":{"x":0,"y":1},"o":{"x":0.5,"y":0}},{"t":60,"s":[90],"h":1}]}},"ip":0,"op":61,"st":0},{"ind":1,"ty":3,"parent":0,"ks":{},"ip":0,"op":61,"st":0},{"ind":0,"ty":3,"ks":{},"ip":0,"op":61,"st":0}],"meta":{"g":"https://jitter.video"},"op":60,"v":"5.7.4","w":400}
|
||||||
"fr": 60,
|
|
||||||
"h": 400,
|
|
||||||
"ip": 0,
|
|
||||||
"layers": [
|
|
||||||
{
|
|
||||||
"ind": 3,
|
|
||||||
"ty": 4,
|
|
||||||
"parent": 2,
|
|
||||||
"ks": {},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 61,
|
|
||||||
"st": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "rc",
|
|
||||||
"p": { "a": 0, "k": [160, 26.75] },
|
|
||||||
"r": { "a": 0, "k": 0 },
|
|
||||||
"s": { "a": 0, "k": [336, 174.5] }
|
|
||||||
},
|
|
||||||
{ "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } },
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "el",
|
|
||||||
"p": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 0.5],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 8.4,
|
|
||||||
"s": [160, 0.5],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 30,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 37.8,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 60, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"s": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [320, 1],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 8.4,
|
|
||||||
"s": [320, 1],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 30,
|
|
||||||
"s": [320, 106],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 37.8,
|
|
||||||
"s": [320, 106],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 60, "s": [320, 1], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": { "a": 0, "k": [0.906, 0.898, 0.894] },
|
|
||||||
"lc": 1,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 10,
|
|
||||||
"o": { "a": 0, "k": 100 },
|
|
||||||
"w": { "a": 0, "k": 16 }
|
|
||||||
},
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 2,
|
|
||||||
"ty": 3,
|
|
||||||
"parent": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 0.5],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 8.4,
|
|
||||||
"s": [160, 0.5],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 30,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 37.8,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 60, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"p": { "a": 0, "k": [200, 200.014] },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{ "t": 0, "s": [-90], "h": 1 },
|
|
||||||
{ "t": 8.4, "s": [-90], "i": { "x": 0, "y": 1 }, "o": { "x": 0.5, "y": 0 } },
|
|
||||||
{ "t": 30, "s": [0], "h": 1 },
|
|
||||||
{ "t": 37.8, "s": [0], "i": { "x": 0, "y": 1 }, "o": { "x": 0.5, "y": 0 } },
|
|
||||||
{ "t": 60, "s": [90], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 61,
|
|
||||||
"st": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 5,
|
|
||||||
"ty": 4,
|
|
||||||
"parent": 4,
|
|
||||||
"ks": {},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 61,
|
|
||||||
"st": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "rc",
|
|
||||||
"p": { "a": 0, "k": [160, 26.75] },
|
|
||||||
"r": { "a": 0, "k": 0 },
|
|
||||||
"s": { "a": 0, "k": [336, 174.5] }
|
|
||||||
},
|
|
||||||
{ "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } },
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "el",
|
|
||||||
"p": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 0.5],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 30,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 60, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"s": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [320, 1],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 30,
|
|
||||||
"s": [320, 106],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 60, "s": [320, 1], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": { "a": 0, "k": [0.906, 0.898, 0.894] },
|
|
||||||
"lc": 1,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 10,
|
|
||||||
"o": { "a": 0, "k": 100 },
|
|
||||||
"w": { "a": 0, "k": 16 }
|
|
||||||
},
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 4,
|
|
||||||
"ty": 3,
|
|
||||||
"parent": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 0.5],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 30,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 60, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"p": { "a": 0, "k": [200.094, 200.19] },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{ "t": 0, "s": [-90], "i": { "x": 0, "y": 1 }, "o": { "x": 0.5, "y": 0 } },
|
|
||||||
{ "t": 30, "s": [0], "i": { "x": 0, "y": 1 }, "o": { "x": 0.5, "y": 0 } },
|
|
||||||
{ "t": 60, "s": [90], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 61,
|
|
||||||
"st": 0
|
|
||||||
},
|
|
||||||
{ "ind": 1, "ty": 3, "parent": 0, "ks": {}, "ip": 0, "op": 61, "st": 0 },
|
|
||||||
{ "ind": 0, "ty": 3, "ks": {}, "ip": 0, "op": 61, "st": 0 }
|
|
||||||
],
|
|
||||||
"meta": { "g": "https://jitter.video" },
|
|
||||||
"op": 60,
|
|
||||||
"v": "5.7.4",
|
|
||||||
"w": 400
|
|
||||||
}
|
|
||||||
@@ -1,281 +1 @@
|
|||||||
{
|
{"fr":60,"h":400,"ip":0,"layers":[{"ind":3,"ty":4,"parent":2,"ks":{},"ip":0,"op":61,"st":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","p":{"a":0,"k":[160,26.75]},"r":{"a":0,"k":0},"s":{"a":0,"k":[336,174.5]}},{"ty":"fl","c":{"a":0,"k":[0,0,0,0]},"o":{"a":0,"k":0}},{"ty":"tr","o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"el","p":{"a":1,"k":[{"t":0,"s":[160,0.5],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":8.4,"s":[160,0.5],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":30,"s":[160,53],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":37.8,"s":[160,53],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":60,"s":[160,0.5],"h":1}]},"s":{"a":1,"k":[{"t":0,"s":[320,1],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":8.4,"s":[320,1],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":30,"s":[320,106],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":37.8,"s":[320,106],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":60,"s":[320,1],"h":1}]}},{"ty":"st","c":{"a":0,"k":[0.11,0.098,0.09]},"lc":1,"lj":1,"ml":10,"o":{"a":0,"k":100},"w":{"a":0,"k":16}},{"ty":"tr","o":{"a":0,"k":100}}]}]},{"ind":2,"ty":3,"parent":1,"ks":{"a":{"a":1,"k":[{"t":0,"s":[160,0.5],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":8.4,"s":[160,0.5],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":30,"s":[160,53],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":37.8,"s":[160,53],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":60,"s":[160,0.5],"h":1}]},"p":{"a":0,"k":[200,200.014]},"r":{"a":1,"k":[{"t":0,"s":[-90],"h":1},{"t":8.4,"s":[-90],"i":{"x":0,"y":1},"o":{"x":0.5,"y":0}},{"t":30,"s":[0],"h":1},{"t":37.8,"s":[0],"i":{"x":0,"y":1},"o":{"x":0.5,"y":0}},{"t":60,"s":[90],"h":1}]}},"ip":0,"op":61,"st":0},{"ind":5,"ty":4,"parent":4,"ks":{},"ip":0,"op":61,"st":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","p":{"a":0,"k":[160,26.75]},"r":{"a":0,"k":0},"s":{"a":0,"k":[336,174.5]}},{"ty":"fl","c":{"a":0,"k":[0,0,0,0]},"o":{"a":0,"k":0}},{"ty":"tr","o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"el","p":{"a":1,"k":[{"t":0,"s":[160,0.5],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":30,"s":[160,53],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":60,"s":[160,0.5],"h":1}]},"s":{"a":1,"k":[{"t":0,"s":[320,1],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":30,"s":[320,106],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":60,"s":[320,1],"h":1}]}},{"ty":"st","c":{"a":0,"k":[0.11,0.098,0.09]},"lc":1,"lj":1,"ml":10,"o":{"a":0,"k":100},"w":{"a":0,"k":16}},{"ty":"tr","o":{"a":0,"k":100}}]}]},{"ind":4,"ty":3,"parent":1,"ks":{"a":{"a":1,"k":[{"t":0,"s":[160,0.5],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":30,"s":[160,53],"i":{"x":[1,0],"y":[1,1]},"o":{"x":[0,0.5],"y":[0,0]}},{"t":60,"s":[160,0.5],"h":1}]},"p":{"a":0,"k":[200.094,200.19]},"r":{"a":1,"k":[{"t":0,"s":[-90],"i":{"x":0,"y":1},"o":{"x":0.5,"y":0}},{"t":30,"s":[0],"i":{"x":0,"y":1},"o":{"x":0.5,"y":0}},{"t":60,"s":[90],"h":1}]}},"ip":0,"op":61,"st":0},{"ind":1,"ty":3,"parent":0,"ks":{},"ip":0,"op":61,"st":0},{"ind":0,"ty":3,"ks":{},"ip":0,"op":61,"st":0}],"meta":{"g":"https://jitter.video"},"op":60,"v":"5.7.4","w":400}
|
||||||
"fr": 60,
|
|
||||||
"h": 400,
|
|
||||||
"ip": 0,
|
|
||||||
"layers": [
|
|
||||||
{
|
|
||||||
"ind": 3,
|
|
||||||
"ty": 4,
|
|
||||||
"parent": 2,
|
|
||||||
"ks": {},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 61,
|
|
||||||
"st": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "rc",
|
|
||||||
"p": { "a": 0, "k": [160, 26.75] },
|
|
||||||
"r": { "a": 0, "k": 0 },
|
|
||||||
"s": { "a": 0, "k": [336, 174.5] }
|
|
||||||
},
|
|
||||||
{ "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } },
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "el",
|
|
||||||
"p": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 0.5],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 8.4,
|
|
||||||
"s": [160, 0.5],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 30,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 37.8,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 60, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"s": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [320, 1],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 8.4,
|
|
||||||
"s": [320, 1],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 30,
|
|
||||||
"s": [320, 106],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 37.8,
|
|
||||||
"s": [320, 106],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 60, "s": [320, 1], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": { "a": 0, "k": [0.11, 0.098, 0.09] },
|
|
||||||
"lc": 1,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 10,
|
|
||||||
"o": { "a": 0, "k": 100 },
|
|
||||||
"w": { "a": 0, "k": 16 }
|
|
||||||
},
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 2,
|
|
||||||
"ty": 3,
|
|
||||||
"parent": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 0.5],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 8.4,
|
|
||||||
"s": [160, 0.5],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 30,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 37.8,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 60, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"p": { "a": 0, "k": [200, 200.014] },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{ "t": 0, "s": [-90], "h": 1 },
|
|
||||||
{ "t": 8.4, "s": [-90], "i": { "x": 0, "y": 1 }, "o": { "x": 0.5, "y": 0 } },
|
|
||||||
{ "t": 30, "s": [0], "h": 1 },
|
|
||||||
{ "t": 37.8, "s": [0], "i": { "x": 0, "y": 1 }, "o": { "x": 0.5, "y": 0 } },
|
|
||||||
{ "t": 60, "s": [90], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 61,
|
|
||||||
"st": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 5,
|
|
||||||
"ty": 4,
|
|
||||||
"parent": 4,
|
|
||||||
"ks": {},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 61,
|
|
||||||
"st": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "rc",
|
|
||||||
"p": { "a": 0, "k": [160, 26.75] },
|
|
||||||
"r": { "a": 0, "k": 0 },
|
|
||||||
"s": { "a": 0, "k": [336, 174.5] }
|
|
||||||
},
|
|
||||||
{ "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } },
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "el",
|
|
||||||
"p": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 0.5],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 30,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 60, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"s": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [320, 1],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 30,
|
|
||||||
"s": [320, 106],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 60, "s": [320, 1], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": { "a": 0, "k": [0.11, 0.098, 0.09] },
|
|
||||||
"lc": 1,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 10,
|
|
||||||
"o": { "a": 0, "k": 100 },
|
|
||||||
"w": { "a": 0, "k": 16 }
|
|
||||||
},
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 4,
|
|
||||||
"ty": 3,
|
|
||||||
"parent": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 0.5],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 30,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0.5], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 60, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"p": { "a": 0, "k": [200.094, 200.19] },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{ "t": 0, "s": [-90], "i": { "x": 0, "y": 1 }, "o": { "x": 0.5, "y": 0 } },
|
|
||||||
{ "t": 30, "s": [0], "i": { "x": 0, "y": 1 }, "o": { "x": 0.5, "y": 0 } },
|
|
||||||
{ "t": 60, "s": [90], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 61,
|
|
||||||
"st": 0
|
|
||||||
},
|
|
||||||
{ "ind": 1, "ty": 3, "parent": 0, "ks": {}, "ip": 0, "op": 61, "st": 0 },
|
|
||||||
{ "ind": 0, "ty": 3, "ks": {}, "ip": 0, "op": 61, "st": 0 }
|
|
||||||
],
|
|
||||||
"meta": { "g": "https://jitter.video" },
|
|
||||||
"op": 60,
|
|
||||||
"v": "5.7.4",
|
|
||||||
"w": 400
|
|
||||||
}
|
|
||||||
@@ -1,224 +1 @@
|
|||||||
{
|
{"fr":60,"h":400,"ip":0,"layers":[{"ind":3,"ty":4,"parent":2,"ks":{},"ip":0,"op":31,"st":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","p":{"a":0,"k":[160,26.75]},"r":{"a":0,"k":0},"s":{"a":0,"k":[336,174.5]}},{"ty":"fl","c":{"a":0,"k":[0,0,0,0]},"o":{"a":0,"k":0}},{"ty":"tr","o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"el","p":{"a":1,"k":[{"t":0,"s":[160,53],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":5.28,"s":[160,53],"i":{"x":[1,0.001],"y":[1,0.998]},"o":{"x":[0,0.349],"y":[0,0]}},{"t":30,"s":[160,0.5],"h":1}]},"s":{"a":1,"k":[{"t":0,"s":[320,106],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":5.28,"s":[320,106],"i":{"x":[1,0.001],"y":[1,0.998]},"o":{"x":[0,0.349],"y":[0,0]}},{"t":30,"s":[320,1],"h":1}]}},{"ty":"st","c":{"a":0,"k":[0.906,0.898,0.894]},"lc":1,"lj":1,"ml":10,"o":{"a":0,"k":100},"w":{"a":0,"k":16}},{"ty":"tr","o":{"a":0,"k":100}}]}]},{"ind":2,"ty":3,"parent":1,"ks":{"a":{"a":1,"k":[{"t":0,"s":[160,53],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":5.28,"s":[160,53],"i":{"x":[1,0.001],"y":[1,0.998]},"o":{"x":[0,0.349],"y":[0,0]}},{"t":30,"s":[160,0.5],"h":1}]},"p":{"a":0,"k":[200.5,200]},"r":{"a":1,"k":[{"t":0,"s":[-30],"h":1},{"t":5.28,"s":[-30],"i":{"x":0.001,"y":0.998},"o":{"x":0.349,"y":0}},{"t":30,"s":[-90],"h":1}]}},"ip":0,"op":31,"st":0},{"ind":5,"ty":4,"parent":4,"ks":{},"ip":0,"op":31,"st":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","p":{"a":0,"k":[160,26.75]},"r":{"a":0,"k":0},"s":{"a":0,"k":[336,174.5]}},{"ty":"fl","c":{"a":0,"k":[0,0,0,0]},"o":{"a":0,"k":0}},{"ty":"tr","o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"el","p":{"a":1,"k":[{"t":0,"s":[160,53],"i":{"x":[1,0],"y":[1,0.999]},"o":{"x":[0,0.348],"y":[0,0]}},{"t":30,"s":[160,0.5],"h":1}]},"s":{"a":1,"k":[{"t":0,"s":[320,106],"i":{"x":[1,0],"y":[1,0.999]},"o":{"x":[0,0.348],"y":[0,0]}},{"t":30,"s":[320,1],"h":1}]}},{"ty":"st","c":{"a":0,"k":[0.906,0.898,0.894]},"lc":1,"lj":1,"ml":10,"o":{"a":0,"k":100},"w":{"a":0,"k":16}},{"ty":"tr","o":{"a":0,"k":100}}]}]},{"ind":4,"ty":3,"parent":1,"ks":{"a":{"a":1,"k":[{"t":0,"s":[160,53],"i":{"x":[1,0],"y":[1,0.999]},"o":{"x":[0,0.348],"y":[0,0]}},{"t":30,"s":[160,0.5],"h":1}]},"p":{"a":0,"k":[200.594,200.176]},"r":{"a":1,"k":[{"t":0,"s":[30],"i":{"x":0,"y":0.999},"o":{"x":0.348,"y":0}},{"t":30,"s":[90],"h":1}]}},"ip":0,"op":31,"st":0},{"ind":1,"ty":3,"parent":0,"ks":{},"ip":0,"op":31,"st":0},{"ind":0,"ty":3,"ks":{},"ip":0,"op":31,"st":0}],"meta":{"g":"https://jitter.video"},"op":30,"v":"5.7.4","w":400}
|
||||||
"fr": 60,
|
|
||||||
"h": 400,
|
|
||||||
"ip": 0,
|
|
||||||
"layers": [
|
|
||||||
{
|
|
||||||
"ind": 3,
|
|
||||||
"ty": 4,
|
|
||||||
"parent": 2,
|
|
||||||
"ks": {},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 31,
|
|
||||||
"st": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "rc",
|
|
||||||
"p": { "a": 0, "k": [160, 26.75] },
|
|
||||||
"r": { "a": 0, "k": 0 },
|
|
||||||
"s": { "a": 0, "k": [336, 174.5] }
|
|
||||||
},
|
|
||||||
{ "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } },
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "el",
|
|
||||||
"p": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 5.28,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0.001], "y": [1, 0.998] },
|
|
||||||
"o": { "x": [0, 0.349], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"s": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [320, 106],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 5.28,
|
|
||||||
"s": [320, 106],
|
|
||||||
"i": { "x": [1, 0.001], "y": [1, 0.998] },
|
|
||||||
"o": { "x": [0, 0.349], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [320, 1], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": { "a": 0, "k": [0.906, 0.898, 0.894] },
|
|
||||||
"lc": 1,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 10,
|
|
||||||
"o": { "a": 0, "k": 100 },
|
|
||||||
"w": { "a": 0, "k": 16 }
|
|
||||||
},
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 2,
|
|
||||||
"ty": 3,
|
|
||||||
"parent": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 5.28,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0.001], "y": [1, 0.998] },
|
|
||||||
"o": { "x": [0, 0.349], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"p": { "a": 0, "k": [200.5, 200] },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{ "t": 0, "s": [-30], "h": 1 },
|
|
||||||
{ "t": 5.28, "s": [-30], "i": { "x": 0.001, "y": 0.998 }, "o": { "x": 0.349, "y": 0 } },
|
|
||||||
{ "t": 30, "s": [-90], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 31,
|
|
||||||
"st": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 5,
|
|
||||||
"ty": 4,
|
|
||||||
"parent": 4,
|
|
||||||
"ks": {},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 31,
|
|
||||||
"st": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "rc",
|
|
||||||
"p": { "a": 0, "k": [160, 26.75] },
|
|
||||||
"r": { "a": 0, "k": 0 },
|
|
||||||
"s": { "a": 0, "k": [336, 174.5] }
|
|
||||||
},
|
|
||||||
{ "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } },
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "el",
|
|
||||||
"p": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 0.999] },
|
|
||||||
"o": { "x": [0, 0.348], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"s": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [320, 106],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 0.999] },
|
|
||||||
"o": { "x": [0, 0.348], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [320, 1], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": { "a": 0, "k": [0.906, 0.898, 0.894] },
|
|
||||||
"lc": 1,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 10,
|
|
||||||
"o": { "a": 0, "k": 100 },
|
|
||||||
"w": { "a": 0, "k": 16 }
|
|
||||||
},
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 4,
|
|
||||||
"ty": 3,
|
|
||||||
"parent": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 0.999] },
|
|
||||||
"o": { "x": [0, 0.348], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"p": { "a": 0, "k": [200.594, 200.176] },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{ "t": 0, "s": [30], "i": { "x": 0, "y": 0.999 }, "o": { "x": 0.348, "y": 0 } },
|
|
||||||
{ "t": 30, "s": [90], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 31,
|
|
||||||
"st": 0
|
|
||||||
},
|
|
||||||
{ "ind": 1, "ty": 3, "parent": 0, "ks": {}, "ip": 0, "op": 31, "st": 0 },
|
|
||||||
{ "ind": 0, "ty": 3, "ks": {}, "ip": 0, "op": 31, "st": 0 }
|
|
||||||
],
|
|
||||||
"meta": { "g": "https://jitter.video" },
|
|
||||||
"op": 30,
|
|
||||||
"v": "5.7.4",
|
|
||||||
"w": 400
|
|
||||||
}
|
|
||||||
@@ -1,224 +1 @@
|
|||||||
{
|
{"fr":60,"h":400,"ip":0,"layers":[{"ind":3,"ty":4,"parent":2,"ks":{},"ip":0,"op":31,"st":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","p":{"a":0,"k":[160,26.75]},"r":{"a":0,"k":0},"s":{"a":0,"k":[336,174.5]}},{"ty":"fl","c":{"a":0,"k":[0,0,0,0]},"o":{"a":0,"k":0}},{"ty":"tr","o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"el","p":{"a":1,"k":[{"t":0,"s":[160,53],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":5.28,"s":[160,53],"i":{"x":[1,0.001],"y":[1,0.998]},"o":{"x":[0,0.349],"y":[0,0]}},{"t":30,"s":[160,0.5],"h":1}]},"s":{"a":1,"k":[{"t":0,"s":[320,106],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":5.28,"s":[320,106],"i":{"x":[1,0.001],"y":[1,0.998]},"o":{"x":[0,0.349],"y":[0,0]}},{"t":30,"s":[320,1],"h":1}]}},{"ty":"st","c":{"a":0,"k":[0.11,0.098,0.09]},"lc":1,"lj":1,"ml":10,"o":{"a":0,"k":100},"w":{"a":0,"k":16}},{"ty":"tr","o":{"a":0,"k":100}}]}]},{"ind":2,"ty":3,"parent":1,"ks":{"a":{"a":1,"k":[{"t":0,"s":[160,53],"i":{"x":[1,1],"y":[1,1]},"o":{"x":[0,0],"y":[0,0]}},{"t":5.28,"s":[160,53],"i":{"x":[1,0.001],"y":[1,0.998]},"o":{"x":[0,0.349],"y":[0,0]}},{"t":30,"s":[160,0.5],"h":1}]},"p":{"a":0,"k":[200.5,200]},"r":{"a":1,"k":[{"t":0,"s":[-30],"h":1},{"t":5.28,"s":[-30],"i":{"x":0.001,"y":0.998},"o":{"x":0.349,"y":0}},{"t":30,"s":[-90],"h":1}]}},"ip":0,"op":31,"st":0},{"ind":5,"ty":4,"parent":4,"ks":{},"ip":0,"op":31,"st":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","p":{"a":0,"k":[160,26.75]},"r":{"a":0,"k":0},"s":{"a":0,"k":[336,174.5]}},{"ty":"fl","c":{"a":0,"k":[0,0,0,0]},"o":{"a":0,"k":0}},{"ty":"tr","o":{"a":0,"k":100}}]},{"ty":"gr","it":[{"ty":"el","p":{"a":1,"k":[{"t":0,"s":[160,53],"i":{"x":[1,0],"y":[1,0.999]},"o":{"x":[0,0.348],"y":[0,0]}},{"t":30,"s":[160,0.5],"h":1}]},"s":{"a":1,"k":[{"t":0,"s":[320,106],"i":{"x":[1,0],"y":[1,0.999]},"o":{"x":[0,0.348],"y":[0,0]}},{"t":30,"s":[320,1],"h":1}]}},{"ty":"st","c":{"a":0,"k":[0.11,0.098,0.09]},"lc":1,"lj":1,"ml":10,"o":{"a":0,"k":100},"w":{"a":0,"k":16}},{"ty":"tr","o":{"a":0,"k":100}}]}]},{"ind":4,"ty":3,"parent":1,"ks":{"a":{"a":1,"k":[{"t":0,"s":[160,53],"i":{"x":[1,0],"y":[1,0.999]},"o":{"x":[0,0.348],"y":[0,0]}},{"t":30,"s":[160,0.5],"h":1}]},"p":{"a":0,"k":[200.594,200.176]},"r":{"a":1,"k":[{"t":0,"s":[30],"i":{"x":0,"y":0.999},"o":{"x":0.348,"y":0}},{"t":30,"s":[90],"h":1}]}},"ip":0,"op":31,"st":0},{"ind":1,"ty":3,"parent":0,"ks":{},"ip":0,"op":31,"st":0},{"ind":0,"ty":3,"ks":{},"ip":0,"op":31,"st":0}],"meta":{"g":"https://jitter.video"},"op":30,"v":"5.7.4","w":400}
|
||||||
"fr": 60,
|
|
||||||
"h": 400,
|
|
||||||
"ip": 0,
|
|
||||||
"layers": [
|
|
||||||
{
|
|
||||||
"ind": 3,
|
|
||||||
"ty": 4,
|
|
||||||
"parent": 2,
|
|
||||||
"ks": {},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 31,
|
|
||||||
"st": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "rc",
|
|
||||||
"p": { "a": 0, "k": [160, 26.75] },
|
|
||||||
"r": { "a": 0, "k": 0 },
|
|
||||||
"s": { "a": 0, "k": [336, 174.5] }
|
|
||||||
},
|
|
||||||
{ "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } },
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "el",
|
|
||||||
"p": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 5.28,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0.001], "y": [1, 0.998] },
|
|
||||||
"o": { "x": [0, 0.349], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"s": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [320, 106],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 5.28,
|
|
||||||
"s": [320, 106],
|
|
||||||
"i": { "x": [1, 0.001], "y": [1, 0.998] },
|
|
||||||
"o": { "x": [0, 0.349], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [320, 1], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": { "a": 0, "k": [0.11, 0.098, 0.09] },
|
|
||||||
"lc": 1,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 10,
|
|
||||||
"o": { "a": 0, "k": 100 },
|
|
||||||
"w": { "a": 0, "k": 16 }
|
|
||||||
},
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 2,
|
|
||||||
"ty": 3,
|
|
||||||
"parent": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 1], "y": [1, 1] },
|
|
||||||
"o": { "x": [0, 0], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"t": 5.28,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0.001], "y": [1, 0.998] },
|
|
||||||
"o": { "x": [0, 0.349], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"p": { "a": 0, "k": [200.5, 200] },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{ "t": 0, "s": [-30], "h": 1 },
|
|
||||||
{ "t": 5.28, "s": [-30], "i": { "x": 0.001, "y": 0.998 }, "o": { "x": 0.349, "y": 0 } },
|
|
||||||
{ "t": 30, "s": [-90], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 31,
|
|
||||||
"st": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 5,
|
|
||||||
"ty": 4,
|
|
||||||
"parent": 4,
|
|
||||||
"ks": {},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 31,
|
|
||||||
"st": 0,
|
|
||||||
"shapes": [
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "rc",
|
|
||||||
"p": { "a": 0, "k": [160, 26.75] },
|
|
||||||
"r": { "a": 0, "k": 0 },
|
|
||||||
"s": { "a": 0, "k": [336, 174.5] }
|
|
||||||
},
|
|
||||||
{ "ty": "fl", "c": { "a": 0, "k": [0, 0, 0, 0] }, "o": { "a": 0, "k": 0 } },
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "gr",
|
|
||||||
"it": [
|
|
||||||
{
|
|
||||||
"ty": "el",
|
|
||||||
"p": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 0.999] },
|
|
||||||
"o": { "x": [0, 0.348], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"s": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [320, 106],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 0.999] },
|
|
||||||
"o": { "x": [0, 0.348], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [320, 1], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ty": "st",
|
|
||||||
"c": { "a": 0, "k": [0.11, 0.098, 0.09] },
|
|
||||||
"lc": 1,
|
|
||||||
"lj": 1,
|
|
||||||
"ml": 10,
|
|
||||||
"o": { "a": 0, "k": 100 },
|
|
||||||
"w": { "a": 0, "k": 16 }
|
|
||||||
},
|
|
||||||
{ "ty": "tr", "o": { "a": 0, "k": 100 } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ind": 4,
|
|
||||||
"ty": 3,
|
|
||||||
"parent": 1,
|
|
||||||
"ks": {
|
|
||||||
"a": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{
|
|
||||||
"t": 0,
|
|
||||||
"s": [160, 53],
|
|
||||||
"i": { "x": [1, 0], "y": [1, 0.999] },
|
|
||||||
"o": { "x": [0, 0.348], "y": [0, 0] }
|
|
||||||
},
|
|
||||||
{ "t": 30, "s": [160, 0.5], "h": 1 }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"p": { "a": 0, "k": [200.594, 200.176] },
|
|
||||||
"r": {
|
|
||||||
"a": 1,
|
|
||||||
"k": [
|
|
||||||
{ "t": 0, "s": [30], "i": { "x": 0, "y": 0.999 }, "o": { "x": 0.348, "y": 0 } },
|
|
||||||
{ "t": 30, "s": [90], "h": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ip": 0,
|
|
||||||
"op": 31,
|
|
||||||
"st": 0
|
|
||||||
},
|
|
||||||
{ "ind": 1, "ty": 3, "parent": 0, "ks": {}, "ip": 0, "op": 31, "st": 0 },
|
|
||||||
{ "ind": 0, "ty": 3, "ks": {}, "ip": 0, "op": 31, "st": 0 }
|
|
||||||
],
|
|
||||||
"meta": { "g": "https://jitter.video" },
|
|
||||||
"op": 30,
|
|
||||||
"v": "5.7.4",
|
|
||||||
"w": 400
|
|
||||||
}
|
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
"@types/react": "^19.2.7",
|
"@types/react": "^19.2.7",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"tailwindcss": "^4.1.13",
|
"tailwindcss": "^4.1.13",
|
||||||
"typescript": "^6",
|
"typescript": "^5.9.2",
|
||||||
"vite": "^7.1.7",
|
"vite": "^7.1.7",
|
||||||
"vite-tsconfig-paths": "^5.1.4"
|
"vite-tsconfig-paths": "^5.1.4"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
{
|
{
|
||||||
"include": ["**/*", "**/.server/**/*", "**/.client/**/*", ".react-router/types/**/*"],
|
"include": ["**/*", "**/.server/**/*", "**/.client/**/*", ".react-router/types/**/*"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"lib": ["DOM", "ES2022"],
|
"lib": ["DOM", "DOM.Iterable", "ES2022"],
|
||||||
"types": ["node", "vite/client"],
|
"types": ["node", "vite/client"],
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
"module": "ES2022",
|
"module": "ES2022",
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"rootDirs": [".", "./.react-router/types"],
|
"rootDirs": [".", "./.react-router/types"],
|
||||||
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"~/*": ["./app/*"]
|
"~/*": ["./app/*"]
|
||||||
},
|
},
|
||||||
|
"esModuleInterop": true,
|
||||||
"verbatimModuleSyntax": true,
|
"verbatimModuleSyntax": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
|
|||||||
367
bun.lock
367
bun.lock
@@ -8,14 +8,11 @@
|
|||||||
"@json-render/core": "^0.12.1",
|
"@json-render/core": "^0.12.1",
|
||||||
"@nym.sh/jrx": "^0.2.0",
|
"@nym.sh/jrx": "^0.2.0",
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
"@typescript/native-preview": "^7.0.0-dev.20260412.1",
|
|
||||||
"husky": "^9.1.7",
|
|
||||||
"lint-staged": "^16.4.0",
|
|
||||||
"oxfmt": "^0.24.0",
|
"oxfmt": "^0.24.0",
|
||||||
"oxlint": "^1.39.0",
|
"oxlint": "^1.39.0",
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "^6",
|
"typescript": "^5",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"apps/admin-dashboard": {
|
"apps/admin-dashboard": {
|
||||||
@@ -40,11 +37,19 @@
|
|||||||
"tw-animate-css": "^1.4.0",
|
"tw-animate-css": "^1.4.0",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.39.1",
|
||||||
"@types/node": "^24.10.1",
|
"@types/node": "^24.10.1",
|
||||||
"@types/react": "^19.2.5",
|
"@types/react": "^19.2.5",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@vitejs/plugin-react": "^5.1.1",
|
"@vitejs/plugin-react": "^5.1.1",
|
||||||
"typescript": "^6",
|
"eslint": "^9.39.1",
|
||||||
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.24",
|
||||||
|
"globals": "^16.5.0",
|
||||||
|
"prettier": "^3.8.1",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.7.2",
|
||||||
|
"typescript": "~5.9.3",
|
||||||
|
"typescript-eslint": "^8.46.4",
|
||||||
"vite": "^7.2.4",
|
"vite": "^7.2.4",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -114,7 +119,7 @@
|
|||||||
"eas-cli": "^18.0.1",
|
"eas-cli": "^18.0.1",
|
||||||
"eslint": "^9.25.0",
|
"eslint": "^9.25.0",
|
||||||
"eslint-config-expo": "~10.0.0",
|
"eslint-config-expo": "~10.0.0",
|
||||||
"typescript": "^6",
|
"typescript": "~5.9.2",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"apps/waitlist-website": {
|
"apps/waitlist-website": {
|
||||||
@@ -141,7 +146,7 @@
|
|||||||
"@types/react": "^19.2.7",
|
"@types/react": "^19.2.7",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"tailwindcss": "^4.1.13",
|
"tailwindcss": "^4.1.13",
|
||||||
"typescript": "^6",
|
"typescript": "^5.9.2",
|
||||||
"vite": "^7.1.7",
|
"vite": "^7.1.7",
|
||||||
"vite-tsconfig-paths": "^5.1.4",
|
"vite-tsconfig-paths": "^5.1.4",
|
||||||
},
|
},
|
||||||
@@ -165,6 +170,14 @@
|
|||||||
"@nym.sh/jrx": "*",
|
"@nym.sh/jrx": "*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"packages/aelis-data-source-weatherkit": {
|
||||||
|
"name": "@aelis/data-source-weatherkit",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@aelis/core": "workspace:*",
|
||||||
|
"arktype": "^2.1.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
"packages/aelis-feed-enhancers": {
|
"packages/aelis-feed-enhancers": {
|
||||||
"name": "@aelis/feed-enhancers",
|
"name": "@aelis/feed-enhancers",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
@@ -235,6 +248,8 @@
|
|||||||
|
|
||||||
"@aelis/core": ["@aelis/core@workspace:packages/aelis-core"],
|
"@aelis/core": ["@aelis/core@workspace:packages/aelis-core"],
|
||||||
|
|
||||||
|
"@aelis/data-source-weatherkit": ["@aelis/data-source-weatherkit@workspace:packages/aelis-data-source-weatherkit"],
|
||||||
|
|
||||||
"@aelis/feed-enhancers": ["@aelis/feed-enhancers@workspace:packages/aelis-feed-enhancers"],
|
"@aelis/feed-enhancers": ["@aelis/feed-enhancers@workspace:packages/aelis-feed-enhancers"],
|
||||||
|
|
||||||
"@aelis/source-caldav": ["@aelis/source-caldav@workspace:packages/aelis-source-caldav"],
|
"@aelis/source-caldav": ["@aelis/source-caldav@workspace:packages/aelis-source-caldav"],
|
||||||
@@ -1435,41 +1450,25 @@
|
|||||||
|
|
||||||
"@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="],
|
"@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="],
|
||||||
|
|
||||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.57.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/type-utils": "8.57.0", "@typescript-eslint/utils": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.57.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ=="],
|
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.57.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.57.1", "@typescript-eslint/type-utils": "8.57.1", "@typescript-eslint/utils": "8.57.1", "@typescript-eslint/visitor-keys": "8.57.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.57.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Gn3aqnvNl4NGc6x3/Bqk1AOn0thyTU9bqDRhiRnUWezgvr2OnhYCWCgC8zXXRVqBsIL1pSDt7T9nJUe0oM0kDQ=="],
|
||||||
|
|
||||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.57.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g=="],
|
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.57.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.57.1", "@typescript-eslint/types": "8.57.1", "@typescript-eslint/typescript-estree": "8.57.1", "@typescript-eslint/visitor-keys": "8.57.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-k4eNDan0EIMTT/dUKc/g+rsJ6wcHYhNPdY19VoX/EOtaAG8DLtKCykhrUnuHPYvinn5jhAPgD2Qw9hXBwrahsw=="],
|
||||||
|
|
||||||
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.57.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.57.0", "@typescript-eslint/types": "^8.57.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w=="],
|
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.57.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.57.1", "@typescript-eslint/types": "^8.57.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vx1F37BRO1OftsYlmG9xay1TqnjNVlqALymwWVuYTdo18XuKxtBpCj1QlzNIEHlvlB27osvXFWptYiEWsVdYsg=="],
|
||||||
|
|
||||||
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0" } }, "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw=="],
|
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.57.1", "", { "dependencies": { "@typescript-eslint/types": "8.57.1", "@typescript-eslint/visitor-keys": "8.57.1" } }, "sha512-hs/QcpCwlwT2L5S+3fT6gp0PabyGk4Q0Rv2doJXA0435/OpnSR3VRgvrp8Xdoc3UAYSg9cyUjTeFXZEPg/3OKg=="],
|
||||||
|
|
||||||
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.57.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA=="],
|
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.57.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-0lgOZB8cl19fHO4eI46YUx2EceQqhgkPSuCGLlGi79L2jwYY1cxeYc1Nae8Aw1xjgW3PKVDLlr3YJ6Bxx8HkWg=="],
|
||||||
|
|
||||||
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0", "@typescript-eslint/utils": "8.57.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ=="],
|
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.57.1", "", { "dependencies": { "@typescript-eslint/types": "8.57.1", "@typescript-eslint/typescript-estree": "8.57.1", "@typescript-eslint/utils": "8.57.1", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-+Bwwm0ScukFdyoJsh2u6pp4S9ktegF98pYUU0hkphOOqdMB+1sNQhIz8y5E9+4pOioZijrkfNO/HUJVAFFfPKA=="],
|
||||||
|
|
||||||
"@typescript-eslint/types": ["@typescript-eslint/types@8.57.0", "", {}, "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg=="],
|
"@typescript-eslint/types": ["@typescript-eslint/types@8.57.1", "", {}, "sha512-S29BOBPJSFUiblEl6RzPPjJt6w25A6XsBqRVDt53tA/tlL8q7ceQNZHTjPeONt/3S7KRI4quk+yP9jK2WjBiPQ=="],
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.57.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.57.0", "@typescript-eslint/tsconfig-utils": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q=="],
|
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.57.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.57.1", "@typescript-eslint/tsconfig-utils": "8.57.1", "@typescript-eslint/types": "8.57.1", "@typescript-eslint/visitor-keys": "8.57.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ybe2hS9G6pXpqGtPli9Gx9quNV0TWLOmh58ADlmZe9DguLq0tiAKVjirSbtM1szG6+QH6rVXyU6GTLQbWnMY+g=="],
|
||||||
|
|
||||||
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.57.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ=="],
|
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.57.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.57.1", "@typescript-eslint/types": "8.57.1", "@typescript-eslint/typescript-estree": "8.57.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-XUNSJ/lEVFttPMMoDVA2r2bwrl8/oPx8cURtczkSEswY5T3AeLmCy+EKWQNdL4u0MmAHOjcWrqJp2cdvgjn8dQ=="],
|
||||||
|
|
||||||
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg=="],
|
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.57.1", "", { "dependencies": { "@typescript-eslint/types": "8.57.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-YWnmJkXbofiz9KbnbbwuA2rpGkFPLbAIetcCNO6mJ8gdhdZ/v7WDXsoGFAJuM6ikUFKTlSQnjWnVO4ux+UzS6A=="],
|
||||||
|
|
||||||
"@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260412.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260412.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260412.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260412.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260412.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260412.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260412.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260412.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-tDw3XZt2BkjAlt/MJmnFGmbe9lgKmc5wezmrMoBIEvJcqz+/KVpVBVvjbkZoaiABnJmuG3G3b6IUFrEveTw6UQ=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260412.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-sSkFG+hjtRWffg6FddF3dEkk7N3TRMEqfiUpixwcWhXgyocMdPw8wutTvQRBxQdgxeL9y01M2SO8A8YPPiEgVg=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260412.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-m2BTeaLkrHEEDg0D9snigddy01qTY+wgx+W+GpXAfx36PPvW4xWuGXNVWfSaB8bqAC9C8NeLnT/C9/G/rJ5v2w=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260412.1", "", { "os": "linux", "cpu": "arm" }, "sha512-wDLekbfsfmKMWORg7CTnEnpKj8oXpU/6AEBrtVN9CEUCiQAe6yH878nZHhJNzWQXHtrtFf3lY49Yplqmdxja3w=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260412.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-JAdsG6MlVV1hoAUKPy8zxAL7xLeNxz8JgCbLCJVqW8EyH29R9FD4cFTqr7CSIRTNUEDzDTrgnXUyoRtDe1gr+w=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260412.1", "", { "os": "linux", "cpu": "x64" }, "sha512-gYgppiQIqid3jZ7D8THh4k3Q+4bwidrQH6SL9Xgbk1qfP6/jwv8twuPqDOfZ+cK2OD55lQHp15fOh2lMNAC40Q=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260412.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-TOh7rH5H3jisHJqRXJSjmUGMzcbNBocS/hufhXPQIv+g3pdG5IKZoSnv3SV62I5d12FFDSS5KQon5MQPnOKAHg=="],
|
|
||||||
|
|
||||||
"@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260412.1", "", { "os": "win32", "cpu": "x64" }, "sha512-u+70wL89wspN1wKoX6FVNUATRGCG3BpleByP3H/UqOZvlwuMm8N7Gy8hEbM0U8bDyAuyP/daUfTBVkqXjjv9mA=="],
|
|
||||||
|
|
||||||
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
|
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
|
||||||
|
|
||||||
@@ -1535,7 +1534,7 @@
|
|||||||
|
|
||||||
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
||||||
|
|
||||||
"ajv": ["ajv@8.11.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg=="],
|
"ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
|
||||||
|
|
||||||
"ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="],
|
"ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="],
|
||||||
|
|
||||||
@@ -1669,7 +1668,7 @@
|
|||||||
|
|
||||||
"bplist-parser": ["bplist-parser@0.3.2", "", { "dependencies": { "big-integer": "1.6.x" } }, "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ=="],
|
"bplist-parser": ["bplist-parser@0.3.2", "", { "dependencies": { "big-integer": "1.6.x" } }, "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ=="],
|
||||||
|
|
||||||
"brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
||||||
|
|
||||||
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
|
||||||
|
|
||||||
@@ -1749,8 +1748,6 @@
|
|||||||
|
|
||||||
"cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
|
"cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
|
||||||
|
|
||||||
"cli-truncate": ["cli-truncate@5.2.0", "", { "dependencies": { "slice-ansi": "^8.0.0", "string-width": "^8.2.0" } }, "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw=="],
|
|
||||||
|
|
||||||
"cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="],
|
"cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="],
|
||||||
|
|
||||||
"client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
|
"client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
|
||||||
@@ -1771,8 +1768,6 @@
|
|||||||
|
|
||||||
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
|
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
|
||||||
|
|
||||||
"colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="],
|
|
||||||
|
|
||||||
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
||||||
|
|
||||||
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
|
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
|
||||||
@@ -1957,8 +1952,6 @@
|
|||||||
|
|
||||||
"envinfo": ["envinfo@7.11.0", "", { "bin": { "envinfo": "dist/cli.js" } }, "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg=="],
|
"envinfo": ["envinfo@7.11.0", "", { "bin": { "envinfo": "dist/cli.js" } }, "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg=="],
|
||||||
|
|
||||||
"environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="],
|
|
||||||
|
|
||||||
"err-code": ["err-code@2.0.3", "", {}, "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="],
|
"err-code": ["err-code@2.0.3", "", {}, "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="],
|
||||||
|
|
||||||
"error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="],
|
"error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="],
|
||||||
@@ -2009,7 +2002,9 @@
|
|||||||
|
|
||||||
"eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="],
|
"eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="],
|
||||||
|
|
||||||
"eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="],
|
"eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@7.0.1", "", { "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA=="],
|
||||||
|
|
||||||
|
"eslint-plugin-react-refresh": ["eslint-plugin-react-refresh@0.4.26", "", { "peerDependencies": { "eslint": ">=8.40" } }, "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ=="],
|
||||||
|
|
||||||
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
|
"eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
|
||||||
|
|
||||||
@@ -2033,8 +2028,6 @@
|
|||||||
|
|
||||||
"event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
|
"event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
|
||||||
|
|
||||||
"eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="],
|
|
||||||
|
|
||||||
"events-universal": ["events-universal@1.0.1", "", { "dependencies": { "bare-events": "^2.7.0" } }, "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw=="],
|
"events-universal": ["events-universal@1.0.1", "", { "dependencies": { "bare-events": "^2.7.0" } }, "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw=="],
|
||||||
|
|
||||||
"eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
|
"eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
|
||||||
@@ -2285,9 +2278,9 @@
|
|||||||
|
|
||||||
"headers-polyfill": ["headers-polyfill@4.0.3", "", {}, "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ=="],
|
"headers-polyfill": ["headers-polyfill@4.0.3", "", {}, "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ=="],
|
||||||
|
|
||||||
"hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
|
"hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="],
|
||||||
|
|
||||||
"hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
"hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="],
|
||||||
|
|
||||||
"hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="],
|
"hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="],
|
||||||
|
|
||||||
@@ -2309,8 +2302,6 @@
|
|||||||
|
|
||||||
"human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="],
|
"human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="],
|
||||||
|
|
||||||
"husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="],
|
|
||||||
|
|
||||||
"hyperlinker": ["hyperlinker@1.0.0", "", {}, "sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ=="],
|
"hyperlinker": ["hyperlinker@1.0.0", "", {}, "sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ=="],
|
||||||
|
|
||||||
"hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="],
|
"hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="],
|
||||||
@@ -2451,7 +2442,7 @@
|
|||||||
|
|
||||||
"isbot": ["isbot@5.1.35", "", {}, "sha512-waFfC72ZNfwLLuJ2iLaoVaqcNo+CAaLR7xCpAn0Y5WfGzkNHv7ZN39Vbi1y+kb+Zs46XHOX3tZNExroFUPX+Kg=="],
|
"isbot": ["isbot@5.1.35", "", {}, "sha512-waFfC72ZNfwLLuJ2iLaoVaqcNo+CAaLR7xCpAn0Y5WfGzkNHv7ZN39Vbi1y+kb+Zs46XHOX3tZNExroFUPX+Kg=="],
|
||||||
|
|
||||||
"isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="],
|
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||||
|
|
||||||
"istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="],
|
"istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="],
|
||||||
|
|
||||||
@@ -2509,7 +2500,7 @@
|
|||||||
|
|
||||||
"json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
|
"json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
|
||||||
|
|
||||||
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
"json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
||||||
|
|
||||||
"json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="],
|
"json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="],
|
||||||
|
|
||||||
@@ -2565,10 +2556,6 @@
|
|||||||
|
|
||||||
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
|
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
|
||||||
|
|
||||||
"lint-staged": ["lint-staged@16.4.0", "", { "dependencies": { "commander": "^14.0.3", "listr2": "^9.0.5", "picomatch": "^4.0.3", "string-argv": "^0.3.2", "tinyexec": "^1.0.4", "yaml": "^2.8.2" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw=="],
|
|
||||||
|
|
||||||
"listr2": ["listr2@9.0.5", "", { "dependencies": { "cli-truncate": "^5.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g=="],
|
|
||||||
|
|
||||||
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
||||||
|
|
||||||
"lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="],
|
"lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="],
|
||||||
@@ -2585,8 +2572,6 @@
|
|||||||
|
|
||||||
"log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="],
|
"log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="],
|
||||||
|
|
||||||
"log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="],
|
|
||||||
|
|
||||||
"long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
"long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
||||||
|
|
||||||
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
|
"longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
|
||||||
@@ -2761,7 +2746,7 @@
|
|||||||
|
|
||||||
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
|
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
|
||||||
|
|
||||||
"minimatch": ["minimatch@5.1.2", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg=="],
|
"minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
||||||
|
|
||||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||||
|
|
||||||
@@ -3011,6 +2996,8 @@
|
|||||||
|
|
||||||
"prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],
|
"prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],
|
||||||
|
|
||||||
|
"prettier-plugin-tailwindcss": ["prettier-plugin-tailwindcss@0.7.2", "", { "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-hermes": "*", "@prettier/plugin-oxc": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", "prettier-plugin-svelte": "*" }, "optionalPeers": ["@ianvs/prettier-plugin-sort-imports", "@prettier/plugin-hermes", "@prettier/plugin-oxc", "@prettier/plugin-pug", "@shopify/prettier-plugin-liquid", "@trivago/prettier-plugin-sort-imports", "@zackad/prettier-plugin-twig", "prettier-plugin-astro", "prettier-plugin-css-order", "prettier-plugin-jsdoc", "prettier-plugin-marko", "prettier-plugin-multiline-arrays", "prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-sort-imports", "prettier-plugin-svelte"] }, "sha512-LkphyK3Fw+q2HdMOoiEHWf93fNtYJwfamoKPl7UwtjFQdei/iIBoX11G6j706FzN3ymX9mPVi97qIY8328vdnA=="],
|
||||||
|
|
||||||
"pretty-bytes": ["pretty-bytes@5.6.0", "", {}, "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg=="],
|
"pretty-bytes": ["pretty-bytes@5.6.0", "", {}, "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg=="],
|
||||||
|
|
||||||
"pretty-format": ["pretty-format@29.7.0", "", { "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ=="],
|
"pretty-format": ["pretty-format@29.7.0", "", { "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ=="],
|
||||||
@@ -3181,8 +3168,6 @@
|
|||||||
|
|
||||||
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
|
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
|
||||||
|
|
||||||
"rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
|
|
||||||
|
|
||||||
"rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="],
|
"rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="],
|
||||||
|
|
||||||
"rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="],
|
"rollup": ["rollup@4.59.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="],
|
||||||
@@ -3271,7 +3256,7 @@
|
|||||||
|
|
||||||
"slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
"slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||||
|
|
||||||
"slice-ansi": ["slice-ansi@8.0.0", "", { "dependencies": { "ansi-styles": "^6.2.3", "is-fullwidth-code-point": "^5.1.0" } }, "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg=="],
|
"slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="],
|
||||||
|
|
||||||
"slugify": ["slugify@1.6.6", "", {}, "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw=="],
|
"slugify": ["slugify@1.6.6", "", {}, "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw=="],
|
||||||
|
|
||||||
@@ -3323,8 +3308,6 @@
|
|||||||
|
|
||||||
"strict-uri-encode": ["strict-uri-encode@2.0.0", "", {}, "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="],
|
"strict-uri-encode": ["strict-uri-encode@2.0.0", "", {}, "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="],
|
||||||
|
|
||||||
"string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="],
|
|
||||||
|
|
||||||
"string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
"string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
||||||
|
|
||||||
"string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
"string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||||
@@ -3363,7 +3346,7 @@
|
|||||||
|
|
||||||
"sucrase": ["sucrase@3.35.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA=="],
|
"sucrase": ["sucrase@3.35.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA=="],
|
||||||
|
|
||||||
"supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||||
|
|
||||||
"supports-hyperlinks": ["supports-hyperlinks@2.3.0", "", { "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" } }, "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA=="],
|
"supports-hyperlinks": ["supports-hyperlinks@2.3.0", "", { "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" } }, "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA=="],
|
||||||
|
|
||||||
@@ -3401,7 +3384,7 @@
|
|||||||
|
|
||||||
"tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
|
"tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
|
||||||
|
|
||||||
"tinyexec": ["tinyexec@1.1.1", "", {}, "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg=="],
|
"tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="],
|
||||||
|
|
||||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||||
|
|
||||||
@@ -3467,7 +3450,9 @@
|
|||||||
|
|
||||||
"typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="],
|
"typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="],
|
||||||
|
|
||||||
"typescript": ["typescript@6.0.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ=="],
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||||
|
|
||||||
|
"typescript-eslint": ["typescript-eslint@8.57.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.57.1", "@typescript-eslint/parser": "8.57.1", "@typescript-eslint/typescript-estree": "8.57.1", "@typescript-eslint/utils": "8.57.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-fLvZWf+cAGw3tqMCYzGIU6yR8K+Y9NT2z23RwOjlNFF2HwSB3KhdEFI5lSBv8tNmFkkBShSjsCjzx1vahZfISA=="],
|
||||||
|
|
||||||
"ua-parser-js": ["ua-parser-js@1.0.41", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug=="],
|
"ua-parser-js": ["ua-parser-js@1.0.41", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug=="],
|
||||||
|
|
||||||
@@ -3573,7 +3558,7 @@
|
|||||||
|
|
||||||
"whatwg-url-without-unicode": ["whatwg-url-without-unicode@8.0.0-3", "", { "dependencies": { "buffer": "^5.4.3", "punycode": "^2.1.1", "webidl-conversions": "^5.0.0" } }, "sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig=="],
|
"whatwg-url-without-unicode": ["whatwg-url-without-unicode@8.0.0-3", "", { "dependencies": { "buffer": "^5.4.3", "punycode": "^2.1.1", "webidl-conversions": "^5.0.0" } }, "sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig=="],
|
||||||
|
|
||||||
"which": ["which@4.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg=="],
|
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||||
|
|
||||||
"which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="],
|
"which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="],
|
||||||
|
|
||||||
@@ -3617,7 +3602,7 @@
|
|||||||
|
|
||||||
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
|
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
|
||||||
|
|
||||||
"yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="],
|
"yaml": ["yaml@2.6.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ=="],
|
||||||
|
|
||||||
"yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
|
"yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
|
||||||
|
|
||||||
@@ -3637,6 +3622,8 @@
|
|||||||
|
|
||||||
"zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
|
"zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
|
||||||
|
|
||||||
|
"zod-validation-error": ["zod-validation-error@4.0.2", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ=="],
|
||||||
|
|
||||||
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
|
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
|
||||||
|
|
||||||
"@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
"@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||||
@@ -3671,20 +3658,16 @@
|
|||||||
|
|
||||||
"@dotenvx/dotenvx/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
"@dotenvx/dotenvx/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
||||||
|
|
||||||
|
"@dotenvx/dotenvx/which": ["which@4.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg=="],
|
||||||
|
|
||||||
"@ecies/ciphers/@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="],
|
"@ecies/ciphers/@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="],
|
||||||
|
|
||||||
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
|
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
|
||||||
|
|
||||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||||
|
|
||||||
"@eslint/config-array/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
|
||||||
|
|
||||||
"@eslint/eslintrc/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
|
|
||||||
|
|
||||||
"@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
|
"@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
|
||||||
|
|
||||||
"@eslint/eslintrc/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
|
||||||
|
|
||||||
"@expo/bunyan/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="],
|
"@expo/bunyan/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="],
|
||||||
|
|
||||||
"@expo/cli/@expo/code-signing-certificates": ["@expo/code-signing-certificates@0.0.6", "", { "dependencies": { "node-forge": "^1.3.3" } }, "sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w=="],
|
"@expo/cli/@expo/code-signing-certificates": ["@expo/code-signing-certificates@0.0.6", "", { "dependencies": { "node-forge": "^1.3.3" } }, "sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w=="],
|
||||||
@@ -3795,6 +3778,8 @@
|
|||||||
|
|
||||||
"@expo/metro-config/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
|
"@expo/metro-config/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
|
||||||
|
|
||||||
|
"@expo/metro-config/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
||||||
|
|
||||||
"@expo/metro-config/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
|
"@expo/metro-config/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
|
||||||
|
|
||||||
"@expo/metro-config/postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="],
|
"@expo/metro-config/postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="],
|
||||||
@@ -3827,8 +3812,6 @@
|
|||||||
|
|
||||||
"@expo/steps/joi": ["joi@17.13.3", "", { "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA=="],
|
"@expo/steps/joi": ["joi@17.13.3", "", { "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA=="],
|
||||||
|
|
||||||
"@expo/steps/yaml": ["yaml@2.6.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ=="],
|
|
||||||
|
|
||||||
"@expo/xcpretty/@babel/code-frame": ["@babel/code-frame@7.23.5", "", { "dependencies": { "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" } }, "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA=="],
|
"@expo/xcpretty/@babel/code-frame": ["@babel/code-frame@7.23.5", "", { "dependencies": { "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" } }, "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA=="],
|
||||||
|
|
||||||
"@formatjs/ecma402-abstract/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"@formatjs/ecma402-abstract/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
@@ -3881,6 +3864,8 @@
|
|||||||
|
|
||||||
"@oclif/core/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
"@oclif/core/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||||
|
|
||||||
|
"@oclif/core/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||||
|
|
||||||
"@prisma/dev/hono": ["hono@4.11.4", "", {}, "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA=="],
|
"@prisma/dev/hono": ["hono@4.11.4", "", {}, "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA=="],
|
||||||
|
|
||||||
"@prisma/dev/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
"@prisma/dev/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
@@ -3893,6 +3878,8 @@
|
|||||||
|
|
||||||
"@react-native/babel-preset/react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="],
|
"@react-native/babel-preset/react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="],
|
||||||
|
|
||||||
|
"@react-native/codegen/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
||||||
|
|
||||||
"@react-native/community-cli-plugin/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
"@react-native/community-cli-plugin/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||||
|
|
||||||
"@react-native/dev-middleware/open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="],
|
"@react-native/dev-middleware/open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="],
|
||||||
@@ -3907,6 +3894,8 @@
|
|||||||
|
|
||||||
"@react-router/dev/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
"@react-router/dev/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||||
|
|
||||||
|
"@segment/ajv-human-errors/ajv": ["ajv@8.11.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg=="],
|
||||||
|
|
||||||
"@swc/helpers/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"@swc/helpers/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
"@tailwindcss/node/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
|
"@tailwindcss/node/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
|
||||||
@@ -3945,12 +3934,16 @@
|
|||||||
|
|
||||||
"accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
|
"accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
|
||||||
|
|
||||||
|
"aelis-client/@tanstack/react-query": ["@tanstack/react-query@5.90.21", "", { "dependencies": { "@tanstack/query-core": "5.90.20" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg=="],
|
||||||
|
|
||||||
"aelis-client/@types/react": ["@types/react@19.1.17", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA=="],
|
"aelis-client/@types/react": ["@types/react@19.1.17", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA=="],
|
||||||
|
|
||||||
"aelis-client/react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="],
|
"aelis-client/react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="],
|
||||||
|
|
||||||
"aelis-client/react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="],
|
"aelis-client/react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="],
|
||||||
|
|
||||||
|
"ajv-formats/ajv": ["ajv@8.11.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg=="],
|
||||||
|
|
||||||
"ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
|
"ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
|
||||||
|
|
||||||
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||||
@@ -3959,6 +3952,8 @@
|
|||||||
|
|
||||||
"babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
"babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||||
|
|
||||||
|
"babel-plugin-syntax-hermes-parser/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
||||||
|
|
||||||
"basic-auth/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
"basic-auth/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||||
|
|
||||||
"better-call/set-cookie-parser": ["set-cookie-parser@3.0.1", "", {}, "sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q=="],
|
"better-call/set-cookie-parser": ["set-cookie-parser@3.0.1", "", {}, "sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q=="],
|
||||||
@@ -3979,8 +3974,6 @@
|
|||||||
|
|
||||||
"c12/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
"c12/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
|
|
||||||
"chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
|
||||||
|
|
||||||
"chevrotain/lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
"chevrotain/lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
|
||||||
|
|
||||||
"chrome-launcher/@types/node": ["@types/node@22.19.15", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg=="],
|
"chrome-launcher/@types/node": ["@types/node@22.19.15", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg=="],
|
||||||
@@ -3993,8 +3986,6 @@
|
|||||||
|
|
||||||
"cli-progress/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
"cli-progress/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||||
|
|
||||||
"cli-truncate/string-width": ["string-width@8.2.0", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw=="],
|
|
||||||
|
|
||||||
"cliui/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
"cliui/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||||
|
|
||||||
"cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
"cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||||
@@ -4009,10 +4000,10 @@
|
|||||||
|
|
||||||
"cross-fetch/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
"cross-fetch/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
||||||
|
|
||||||
"cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
|
||||||
|
|
||||||
"dotenv-expand/dotenv": ["dotenv@16.4.7", "", {}, "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ=="],
|
"dotenv-expand/dotenv": ["dotenv@16.4.7", "", {}, "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ=="],
|
||||||
|
|
||||||
|
"eas-cli/ajv": ["ajv@8.11.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg=="],
|
||||||
|
|
||||||
"eas-cli/diff": ["diff@7.0.0", "", {}, "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw=="],
|
"eas-cli/diff": ["diff@7.0.0", "", {}, "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw=="],
|
||||||
|
|
||||||
"eas-cli/fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="],
|
"eas-cli/fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="],
|
||||||
@@ -4021,19 +4012,21 @@
|
|||||||
|
|
||||||
"eas-cli/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
|
"eas-cli/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
|
||||||
|
|
||||||
|
"eas-cli/minimatch": ["minimatch@5.1.2", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg=="],
|
||||||
|
|
||||||
"eas-cli/node-fetch": ["node-fetch@2.6.7", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ=="],
|
"eas-cli/node-fetch": ["node-fetch@2.6.7", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ=="],
|
||||||
|
|
||||||
"eas-cli/ora": ["ora@5.1.0", "", { "dependencies": { "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.4.0", "is-interactive": "^1.0.0", "log-symbols": "^4.0.0", "mute-stream": "0.0.8", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-9tXIMPvjZ7hPTbk8DFq1f7Kow/HU/pQYB60JbNq+QnGwcyhWVZaQ4hM9zQDEsPxw/muLpgiHSaumUZxCAmod/w=="],
|
"eas-cli/ora": ["ora@5.1.0", "", { "dependencies": { "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.4.0", "is-interactive": "^1.0.0", "log-symbols": "^4.0.0", "mute-stream": "0.0.8", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-9tXIMPvjZ7hPTbk8DFq1f7Kow/HU/pQYB60JbNq+QnGwcyhWVZaQ4hM9zQDEsPxw/muLpgiHSaumUZxCAmod/w=="],
|
||||||
|
|
||||||
"eas-cli/yaml": ["yaml@2.6.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ=="],
|
|
||||||
|
|
||||||
"eciesjs/@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="],
|
"eciesjs/@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="],
|
||||||
|
|
||||||
"eciesjs/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
|
"eciesjs/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
|
||||||
|
|
||||||
"eslint/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
|
"eslint-config-expo/@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.57.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/type-utils": "8.57.0", "@typescript-eslint/utils": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.57.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ=="],
|
||||||
|
|
||||||
"eslint/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
"eslint-config-expo/@typescript-eslint/parser": ["@typescript-eslint/parser@8.57.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="],
|
||||||
|
|
||||||
"eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
"eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||||
|
|
||||||
@@ -4041,16 +4034,16 @@
|
|||||||
|
|
||||||
"eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
"eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||||
|
|
||||||
"eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
"eslint-plugin-expo/@typescript-eslint/types": ["@typescript-eslint/types@8.57.0", "", {}, "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg=="],
|
||||||
|
|
||||||
"eslint-plugin-import/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
"eslint-plugin-expo/@typescript-eslint/utils": ["@typescript-eslint/utils@8.57.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ=="],
|
||||||
|
|
||||||
|
"eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||||
|
|
||||||
"eslint-plugin-import/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
"eslint-plugin-import/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||||
|
|
||||||
"eslint-plugin-import/tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="],
|
"eslint-plugin-import/tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="],
|
||||||
|
|
||||||
"eslint-plugin-react/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
|
||||||
|
|
||||||
"eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
"eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||||
|
|
||||||
"execa/figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="],
|
"execa/figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="],
|
||||||
@@ -4067,6 +4060,8 @@
|
|||||||
|
|
||||||
"expo-constants/@expo/env": ["@expo/env@2.0.11", "", { "dependencies": { "chalk": "^4.0.0", "debug": "^4.3.4", "dotenv": "~16.4.5", "dotenv-expand": "~11.0.6", "getenv": "^2.0.0" } }, "sha512-xV+ps6YCW7XIPVUwFVCRN2nox09dnRwy8uIjwHWTODu0zFw4kp4omnVkl0OOjuu2XOe7tdgAHxikrkJt9xB/7Q=="],
|
"expo-constants/@expo/env": ["@expo/env@2.0.11", "", { "dependencies": { "chalk": "^4.0.0", "debug": "^4.3.4", "dotenv": "~16.4.5", "dotenv-expand": "~11.0.6", "getenv": "^2.0.0" } }, "sha512-xV+ps6YCW7XIPVUwFVCRN2nox09dnRwy8uIjwHWTODu0zFw4kp4omnVkl0OOjuu2XOe7tdgAHxikrkJt9xB/7Q=="],
|
||||||
|
|
||||||
|
"expo-dev-launcher/ajv": ["ajv@8.11.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg=="],
|
||||||
|
|
||||||
"expo-manifests/@expo/config": ["@expo/config@12.0.13", "", { "dependencies": { "@babel/code-frame": "~7.10.4", "@expo/config-plugins": "~54.0.4", "@expo/config-types": "^54.0.10", "@expo/json-file": "^10.0.8", "deepmerge": "^4.3.1", "getenv": "^2.0.0", "glob": "^13.0.0", "require-from-string": "^2.0.2", "resolve-from": "^5.0.0", "resolve-workspace-root": "^2.0.0", "semver": "^7.6.0", "slugify": "^1.3.4", "sucrase": "~3.35.1" } }, "sha512-Cu52arBa4vSaupIWsF0h7F/Cg//N374nYb7HAxV0I4KceKA7x2UXpYaHOL7EEYYvp7tZdThBjvGpVmr8ScIvaQ=="],
|
"expo-manifests/@expo/config": ["@expo/config@12.0.13", "", { "dependencies": { "@babel/code-frame": "~7.10.4", "@expo/config-plugins": "~54.0.4", "@expo/config-types": "^54.0.10", "@expo/json-file": "^10.0.8", "deepmerge": "^4.3.1", "getenv": "^2.0.0", "glob": "^13.0.0", "require-from-string": "^2.0.2", "resolve-from": "^5.0.0", "resolve-workspace-root": "^2.0.0", "semver": "^7.6.0", "slugify": "^1.3.4", "sucrase": "~3.35.1" } }, "sha512-Cu52arBa4vSaupIWsF0h7F/Cg//N374nYb7HAxV0I4KceKA7x2UXpYaHOL7EEYYvp7tZdThBjvGpVmr8ScIvaQ=="],
|
||||||
|
|
||||||
"expo-modules-autolinking/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
|
"expo-modules-autolinking/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
|
||||||
@@ -4093,14 +4088,14 @@
|
|||||||
|
|
||||||
"figures/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
"figures/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
||||||
|
|
||||||
|
"filelist/minimatch": ["minimatch@5.1.2", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-bNH9mmM9qsJ2X4r2Nat1B//1dJVcn3+iBLa3IgqJ7EbGaDNepL9QSHOxN4ng33s52VMMhhIfgCYDk3C4ZmlDAg=="],
|
||||||
|
|
||||||
"finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
"finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||||
|
|
||||||
"framer-motion/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"framer-motion/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
"giget/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
"giget/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
|
|
||||||
"glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
|
||||||
|
|
||||||
"globby/fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="],
|
"globby/fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="],
|
||||||
|
|
||||||
"globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
"globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
||||||
@@ -4135,18 +4130,12 @@
|
|||||||
|
|
||||||
"jest-worker/@types/node": ["@types/node@22.19.15", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg=="],
|
"jest-worker/@types/node": ["@types/node@22.19.15", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg=="],
|
||||||
|
|
||||||
|
"jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||||
|
|
||||||
"lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
"lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||||
|
|
||||||
"listr2/wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
|
||||||
|
|
||||||
"log-symbols/is-unicode-supported": ["is-unicode-supported@0.1.0", "", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="],
|
"log-symbols/is-unicode-supported": ["is-unicode-supported@0.1.0", "", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="],
|
||||||
|
|
||||||
"log-update/ansi-escapes": ["ansi-escapes@7.3.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg=="],
|
|
||||||
|
|
||||||
"log-update/slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="],
|
|
||||||
|
|
||||||
"log-update/wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
|
||||||
|
|
||||||
"lru-cache/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
"lru-cache/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||||
|
|
||||||
"mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
|
"mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
|
||||||
@@ -4167,6 +4156,8 @@
|
|||||||
|
|
||||||
"metro-config/metro-runtime": ["metro-runtime@0.83.3", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw=="],
|
"metro-config/metro-runtime": ["metro-runtime@0.83.3", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw=="],
|
||||||
|
|
||||||
|
"metro-config/yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="],
|
||||||
|
|
||||||
"metro-source-map/metro-symbolicate": ["metro-symbolicate@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.5", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-EMIkrjNRz/hF+p0RDdxoE60+dkaTLPN3vaaGkFmX5lvFdO6HPfHA/Ywznzkev+za0VhPQ5KSdz49/MALBRteHA=="],
|
"metro-source-map/metro-symbolicate": ["metro-symbolicate@0.83.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.5", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-EMIkrjNRz/hF+p0RDdxoE60+dkaTLPN3vaaGkFmX5lvFdO6HPfHA/Ywznzkev+za0VhPQ5KSdz49/MALBRteHA=="],
|
||||||
|
|
||||||
"metro-source-map/source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="],
|
"metro-source-map/source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="],
|
||||||
@@ -4201,8 +4192,6 @@
|
|||||||
|
|
||||||
"nypm/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
"nypm/pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
|
|
||||||
"nypm/tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="],
|
|
||||||
|
|
||||||
"ora/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
"ora/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
||||||
|
|
||||||
"ora/log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="],
|
"ora/log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="],
|
||||||
@@ -4281,10 +4270,6 @@
|
|||||||
|
|
||||||
"simple-swizzle/is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="],
|
"simple-swizzle/is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="],
|
||||||
|
|
||||||
"slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
|
||||||
|
|
||||||
"slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="],
|
|
||||||
|
|
||||||
"stack-utils/escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="],
|
"stack-utils/escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="],
|
||||||
|
|
||||||
"stacktrace-parser/type-fest": ["type-fest@0.7.1", "", {}, "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg=="],
|
"stacktrace-parser/type-fest": ["type-fest@0.7.1", "", {}, "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg=="],
|
||||||
@@ -4299,16 +4284,12 @@
|
|||||||
|
|
||||||
"sucrase/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
|
"sucrase/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
|
||||||
|
|
||||||
"supports-hyperlinks/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
|
||||||
|
|
||||||
"svix/uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="],
|
"svix/uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="],
|
||||||
|
|
||||||
"tar/minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
|
"tar/minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
|
||||||
|
|
||||||
"terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
"terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
||||||
|
|
||||||
"test-exclude/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
|
||||||
|
|
||||||
"ts-node/arg": ["arg@4.1.3", "", {}, "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="],
|
"ts-node/arg": ["arg@4.1.3", "", {}, "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="],
|
||||||
|
|
||||||
"ts-node/diff": ["diff@4.0.4", "", {}, "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ=="],
|
"ts-node/diff": ["diff@4.0.4", "", {}, "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ=="],
|
||||||
@@ -4363,6 +4344,8 @@
|
|||||||
|
|
||||||
"@dotenvx/dotenvx/execa/strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
|
"@dotenvx/dotenvx/execa/strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
|
||||||
|
|
||||||
|
"@dotenvx/dotenvx/which/isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="],
|
||||||
|
|
||||||
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
|
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
|
||||||
|
|
||||||
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
|
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
|
||||||
@@ -4407,12 +4390,6 @@
|
|||||||
|
|
||||||
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
|
"@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="],
|
||||||
|
|
||||||
"@eslint/config-array/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
|
||||||
|
|
||||||
"@eslint/eslintrc/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
|
||||||
|
|
||||||
"@eslint/eslintrc/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
|
||||||
|
|
||||||
"@expo/cli/@expo/config/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
"@expo/cli/@expo/config/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
||||||
|
|
||||||
"@expo/cli/@expo/config/@expo/config-types": ["@expo/config-types@54.0.10", "", {}, "sha512-/J16SC2an1LdtCZ67xhSkGXpALYUVUNyZws7v+PVsFZxClYehDSoKLqyRaGkpHlYrCc08bS0RF5E0JV6g50psA=="],
|
"@expo/cli/@expo/config/@expo/config-types": ["@expo/config-types@54.0.10", "", {}, "sha512-/J16SC2an1LdtCZ67xhSkGXpALYUVUNyZws7v+PVsFZxClYehDSoKLqyRaGkpHlYrCc08bS0RF5E0JV6g50psA=="],
|
||||||
@@ -4435,6 +4412,8 @@
|
|||||||
|
|
||||||
"@expo/cli/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
|
"@expo/cli/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
|
||||||
|
|
||||||
|
"@expo/cli/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||||
|
|
||||||
"@expo/cli/ora/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
"@expo/cli/ora/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
||||||
|
|
||||||
"@expo/cli/ora/cli-cursor": ["cli-cursor@2.1.0", "", { "dependencies": { "restore-cursor": "^2.0.0" } }, "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw=="],
|
"@expo/cli/ora/cli-cursor": ["cli-cursor@2.1.0", "", { "dependencies": { "restore-cursor": "^2.0.0" } }, "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw=="],
|
||||||
@@ -4455,6 +4434,8 @@
|
|||||||
|
|
||||||
"@expo/fingerprint/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
|
"@expo/fingerprint/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
|
||||||
|
|
||||||
|
"@expo/fingerprint/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||||
|
|
||||||
"@expo/image-utils/fs-extra/universalify": ["universalify@1.0.0", "", {}, "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="],
|
"@expo/image-utils/fs-extra/universalify": ["universalify@1.0.0", "", {}, "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="],
|
||||||
|
|
||||||
"@expo/metro-config/@babel/code-frame/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
"@expo/metro-config/@babel/code-frame/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
||||||
@@ -4473,6 +4454,10 @@
|
|||||||
|
|
||||||
"@expo/metro-config/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
|
"@expo/metro-config/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
|
||||||
|
|
||||||
|
"@expo/metro-config/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
|
||||||
|
|
||||||
|
"@expo/metro-config/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||||
|
|
||||||
"@expo/metro-config/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
"@expo/metro-config/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||||
|
|
||||||
"@expo/metro/metro-source-map/ob1": ["ob1@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA=="],
|
"@expo/metro/metro-source-map/ob1": ["ob1@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA=="],
|
||||||
@@ -4491,20 +4476,20 @@
|
|||||||
|
|
||||||
"@expo/plugin-help/@oclif/core/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="],
|
"@expo/plugin-help/@oclif/core/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="],
|
||||||
|
|
||||||
"@expo/plugin-help/@oclif/core/slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="],
|
|
||||||
|
|
||||||
"@expo/plugin-help/@oclif/core/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
"@expo/plugin-help/@oclif/core/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||||
|
|
||||||
"@expo/plugin-help/@oclif/core/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
"@expo/plugin-help/@oclif/core/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||||
|
|
||||||
"@expo/plugin-warn-if-update-available/@oclif/core/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="],
|
"@expo/plugin-help/@oclif/core/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||||
|
|
||||||
"@expo/plugin-warn-if-update-available/@oclif/core/slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="],
|
"@expo/plugin-warn-if-update-available/@oclif/core/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="],
|
||||||
|
|
||||||
"@expo/plugin-warn-if-update-available/@oclif/core/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
"@expo/plugin-warn-if-update-available/@oclif/core/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||||
|
|
||||||
"@expo/plugin-warn-if-update-available/@oclif/core/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
"@expo/plugin-warn-if-update-available/@oclif/core/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||||
|
|
||||||
|
"@expo/plugin-warn-if-update-available/@oclif/core/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||||
|
|
||||||
"@expo/prebuild-config/@expo/json-file/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
"@expo/prebuild-config/@expo/json-file/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
||||||
|
|
||||||
"@expo/xcpretty/@babel/code-frame/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
"@expo/xcpretty/@babel/code-frame/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
||||||
@@ -4529,6 +4514,8 @@
|
|||||||
|
|
||||||
"@jest/types/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
"@jest/types/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
||||||
|
|
||||||
|
"@modelcontextprotocol/sdk/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||||
|
|
||||||
"@modelcontextprotocol/sdk/express/accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
"@modelcontextprotocol/sdk/express/accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
||||||
|
|
||||||
"@modelcontextprotocol/sdk/express/body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="],
|
"@modelcontextprotocol/sdk/express/body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="],
|
||||||
@@ -4559,8 +4546,12 @@
|
|||||||
|
|
||||||
"@oclif/core/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
"@oclif/core/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||||
|
|
||||||
|
"@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
|
||||||
|
|
||||||
"@react-native/dev-middleware/open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="],
|
"@react-native/dev-middleware/open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="],
|
||||||
|
|
||||||
|
"@segment/ajv-human-errors/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="],
|
"@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="],
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="],
|
"@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="],
|
||||||
@@ -4603,8 +4594,14 @@
|
|||||||
|
|
||||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="],
|
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="],
|
||||||
|
|
||||||
|
"aelis-client/@tanstack/react-query/@tanstack/query-core": ["@tanstack/query-core@5.90.20", "", {}, "sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg=="],
|
||||||
|
|
||||||
"aelis-client/react-dom/scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
|
"aelis-client/react-dom/scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
|
||||||
|
|
||||||
|
"ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||||
|
|
||||||
|
"babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
|
||||||
|
|
||||||
"better-opn/open/define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="],
|
"better-opn/open/define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="],
|
||||||
|
|
||||||
"better-opn/open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="],
|
"better-opn/open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="],
|
||||||
@@ -4633,28 +4630,44 @@
|
|||||||
|
|
||||||
"connect/finalhandler/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="],
|
"connect/finalhandler/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="],
|
||||||
|
|
||||||
"cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
"eas-cli/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||||
|
|
||||||
"eas-cli/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
"eas-cli/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||||
|
|
||||||
"eas-cli/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
|
"eas-cli/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
|
||||||
|
|
||||||
|
"eas-cli/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||||
|
|
||||||
"eas-cli/ora/cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
|
"eas-cli/ora/cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
|
||||||
|
|
||||||
"eas-cli/ora/is-interactive": ["is-interactive@1.0.0", "", {}, "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="],
|
"eas-cli/ora/is-interactive": ["is-interactive@1.0.0", "", {}, "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="],
|
||||||
|
|
||||||
"eas-cli/ora/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
"eas-cli/ora/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||||
|
|
||||||
"eslint-plugin-import/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0" } }, "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0", "@typescript-eslint/utils": "8.57.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/utils": ["@typescript-eslint/utils@8.57.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/parser/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0" } }, "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.57.0", "", {}, "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/parser/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.57.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.57.0", "@typescript-eslint/tsconfig-utils": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/parser/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg=="],
|
||||||
|
|
||||||
|
"eslint-plugin-expo/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0" } }, "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw=="],
|
||||||
|
|
||||||
|
"eslint-plugin-expo/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.57.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.57.0", "@typescript-eslint/tsconfig-utils": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q=="],
|
||||||
|
|
||||||
"eslint-plugin-import/tsconfig-paths/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="],
|
"eslint-plugin-import/tsconfig-paths/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="],
|
||||||
|
|
||||||
"eslint-plugin-react/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
|
||||||
|
|
||||||
"eslint/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
|
||||||
|
|
||||||
"eslint/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
|
||||||
|
|
||||||
"expo-asset/@expo/image-utils/getenv": ["getenv@2.0.0", "", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="],
|
"expo-asset/@expo/image-utils/getenv": ["getenv@2.0.0", "", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="],
|
||||||
|
|
||||||
"expo-asset/@expo/image-utils/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
"expo-asset/@expo/image-utils/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||||
@@ -4679,6 +4692,8 @@
|
|||||||
|
|
||||||
"expo-constants/@expo/env/getenv": ["getenv@2.0.0", "", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="],
|
"expo-constants/@expo/env/getenv": ["getenv@2.0.0", "", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="],
|
||||||
|
|
||||||
|
"expo-dev-launcher/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||||
|
|
||||||
"expo-manifests/@expo/config/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
"expo-manifests/@expo/config/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
||||||
|
|
||||||
"expo-manifests/@expo/config/@expo/config-plugins": ["@expo/config-plugins@54.0.4", "", { "dependencies": { "@expo/config-types": "^54.0.10", "@expo/json-file": "~10.0.8", "@expo/plist": "^0.4.8", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-from": "^5.0.0", "semver": "^7.5.4", "slash": "^3.0.0", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-g2yXGICdoOw5i3LkQSDxl2Q5AlQCrG7oniu0pCPPO+UxGb7He4AFqSvPSy8HpRUj55io17hT62FTjYRD+d6j3Q=="],
|
"expo-manifests/@expo/config/@expo/config-plugins": ["@expo/config-plugins@54.0.4", "", { "dependencies": { "@expo/config-types": "^54.0.10", "@expo/json-file": "~10.0.8", "@expo/plist": "^0.4.8", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-from": "^5.0.0", "semver": "^7.5.4", "slash": "^3.0.0", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-g2yXGICdoOw5i3LkQSDxl2Q5AlQCrG7oniu0pCPPO+UxGb7He4AFqSvPSy8HpRUj55io17hT62FTjYRD+d6j3Q=="],
|
||||||
@@ -4737,9 +4752,9 @@
|
|||||||
|
|
||||||
"fbjs/cross-fetch/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
"fbjs/cross-fetch/node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
||||||
|
|
||||||
"finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
"filelist/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||||
|
|
||||||
"glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
"finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||||
|
|
||||||
"globby/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
"globby/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||||
|
|
||||||
@@ -4755,14 +4770,6 @@
|
|||||||
|
|
||||||
"lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
"lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||||
|
|
||||||
"listr2/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
|
||||||
|
|
||||||
"log-update/slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
|
||||||
|
|
||||||
"log-update/slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="],
|
|
||||||
|
|
||||||
"log-update/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
|
||||||
|
|
||||||
"metro-babel-transformer/hermes-parser/hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="],
|
"metro-babel-transformer/hermes-parser/hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="],
|
||||||
|
|
||||||
"metro-symbolicate/metro-source-map/ob1": ["ob1@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA=="],
|
"metro-symbolicate/metro-source-map/ob1": ["ob1@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA=="],
|
||||||
@@ -4793,8 +4800,6 @@
|
|||||||
|
|
||||||
"sucrase/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
|
"sucrase/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
|
||||||
|
|
||||||
"test-exclude/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
|
||||||
|
|
||||||
"twrnc/tailwindcss/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
|
"twrnc/tailwindcss/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
|
||||||
|
|
||||||
"twrnc/tailwindcss/fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="],
|
"twrnc/tailwindcss/fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="],
|
||||||
@@ -4895,6 +4900,10 @@
|
|||||||
|
|
||||||
"@expo/cli/ora/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
|
"@expo/cli/ora/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
|
||||||
|
|
||||||
|
"@expo/config-plugins/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||||
|
|
||||||
|
"@expo/config/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||||
|
|
||||||
"@expo/eas-json/@babel/code-frame/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
"@expo/eas-json/@babel/code-frame/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
||||||
|
|
||||||
"@expo/eas-json/@babel/code-frame/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
"@expo/eas-json/@babel/code-frame/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
||||||
@@ -4963,6 +4972,42 @@
|
|||||||
|
|
||||||
"eas-cli/ora/cli-cursor/restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="],
|
"eas-cli/ora/cli-cursor/restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.57.0", "", {}, "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/types": ["@typescript-eslint/types@8.57.0", "", {}, "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.57.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.57.0", "@typescript-eslint/tsconfig-utils": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.57.0", "", {}, "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.57.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.57.0", "@typescript-eslint/tsconfig-utils": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.57.0", "", {}, "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/parser/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.57.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.57.0", "@typescript-eslint/types": "^8.57.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/parser/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.57.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/parser/@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/parser/@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/parser/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
|
||||||
|
|
||||||
|
"eslint-plugin-expo/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg=="],
|
||||||
|
|
||||||
|
"eslint-plugin-expo/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.57.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.57.0", "@typescript-eslint/types": "^8.57.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w=="],
|
||||||
|
|
||||||
|
"eslint-plugin-expo/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.57.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA=="],
|
||||||
|
|
||||||
|
"eslint-plugin-expo/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg=="],
|
||||||
|
|
||||||
|
"eslint-plugin-expo/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
|
||||||
|
|
||||||
|
"eslint-plugin-expo/@typescript-eslint/utils/@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||||
|
|
||||||
"expo-constants/@expo/config/@expo/config-plugins/@expo/plist": ["@expo/plist@0.4.8", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.2.3", "xmlbuilder": "^15.1.1" } }, "sha512-pfNtErGGzzRwHP+5+RqswzPDKkZrx+Cli0mzjQaus1ZWFsog5ibL+nVT3NcporW51o8ggnt7x813vtRbPiyOrQ=="],
|
"expo-constants/@expo/config/@expo/config-plugins/@expo/plist": ["@expo/plist@0.4.8", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.2.3", "xmlbuilder": "^15.1.1" } }, "sha512-pfNtErGGzzRwHP+5+RqswzPDKkZrx+Cli0mzjQaus1ZWFsog5ibL+nVT3NcporW51o8ggnt7x813vtRbPiyOrQ=="],
|
||||||
|
|
||||||
"expo-constants/@expo/config/@expo/json-file/@babel/code-frame": ["@babel/code-frame@7.23.5", "", { "dependencies": { "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" } }, "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA=="],
|
"expo-constants/@expo/config/@expo/json-file/@babel/code-frame": ["@babel/code-frame@7.23.5", "", { "dependencies": { "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" } }, "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA=="],
|
||||||
@@ -5019,10 +5064,12 @@
|
|||||||
|
|
||||||
"expo/@expo/config/sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
|
"expo/@expo/config/sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
|
||||||
|
|
||||||
"mv/rimraf/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
|
||||||
|
|
||||||
"pkg-dir/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
"pkg-dir/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
||||||
|
|
||||||
|
"rimraf/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||||
|
|
||||||
|
"sucrase/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||||
|
|
||||||
"twrnc/tailwindcss/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
"twrnc/tailwindcss/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||||
|
|
||||||
"twrnc/tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
|
"twrnc/tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
|
||||||
@@ -5089,6 +5136,30 @@
|
|||||||
|
|
||||||
"eas-cli/ora/cli-cursor/restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
"eas-cli/ora/cli-cursor/restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.57.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.57.0", "@typescript-eslint/types": "^8.57.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.57.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.57.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.57.0", "@typescript-eslint/types": "^8.57.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.57.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/parser/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="],
|
||||||
|
|
||||||
|
"eslint-plugin-expo/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
|
||||||
|
|
||||||
|
"eslint-plugin-expo/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
|
||||||
|
|
||||||
|
"eslint-plugin-expo/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="],
|
||||||
|
|
||||||
"expo-constants/@expo/config/@expo/config-plugins/@expo/plist/@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="],
|
"expo-constants/@expo/config/@expo/config-plugins/@expo/plist/@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="],
|
||||||
|
|
||||||
"expo-constants/@expo/config/@expo/config-plugins/@expo/plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="],
|
"expo-constants/@expo/config/@expo/config-plugins/@expo/plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="],
|
||||||
@@ -5137,8 +5208,6 @@
|
|||||||
|
|
||||||
"expo/@expo/config/glob/path-scurry/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="],
|
"expo/@expo/config/glob/path-scurry/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="],
|
||||||
|
|
||||||
"mv/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
|
||||||
|
|
||||||
"pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
"pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
||||||
|
|
||||||
"twrnc/tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
"twrnc/tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||||
@@ -5165,6 +5234,14 @@
|
|||||||
|
|
||||||
"@expo/xcpretty/@babel/code-frame/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
"@expo/xcpretty/@babel/code-frame/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/parser/@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||||
|
|
||||||
|
"eslint-plugin-expo/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||||
|
|
||||||
"expo-constants/@expo/config/@expo/json-file/@babel/code-frame/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
"expo-constants/@expo/config/@expo/json-file/@babel/code-frame/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
||||||
|
|
||||||
"expo-constants/@expo/config/@expo/json-file/@babel/code-frame/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
"expo-constants/@expo/config/@expo/json-file/@babel/code-frame/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
||||||
@@ -5215,6 +5292,10 @@
|
|||||||
|
|
||||||
"@expo/package-manager/@expo/json-file/@babel/code-frame/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
"@expo/package-manager/@expo/json-file/@babel/code-frame/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||||
|
|
||||||
|
"eslint-config-expo/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||||
|
|
||||||
"expo-constants/@expo/config/@expo/json-file/@babel/code-frame/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
"expo-constants/@expo/config/@expo/json-file/@babel/code-frame/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||||
|
|
||||||
"expo-constants/@expo/config/@expo/json-file/@babel/code-frame/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
"expo-constants/@expo/config/@expo/json-file/@babel/code-frame/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ Sources → Source Graph → FeedEngine
|
|||||||
|
|
||||||
### One harness, not many agents
|
### One harness, not many agents
|
||||||
|
|
||||||
The "agents" in this doc describe _behaviors_, not separate running processes. A human PA is one person — they don't have a "calendar agent" and a "follow-up agent" in their head. They look at your whole situation and act on whatever matters.
|
The "agents" in this doc describe *behaviors*, not separate running processes. A human PA is one person — they don't have a "calendar agent" and a "follow-up agent" in their head. They look at your whole situation and act on whatever matters.
|
||||||
|
|
||||||
AELIS works the same way. One LLM harness receives all feed items, all context, all user memory, and all available tools. It returns a single `FeedEnhancement`. Every behavior (preparation, follow-up, anomaly detection, tone adjustment, cross-source reasoning) is an instruction in the system prompt, not a separate agent.
|
AELIS works the same way. One LLM harness receives all feed items, all context, all user memory, and all available tools. It returns a single `FeedEnhancement`. Every behavior (preparation, follow-up, anomaly detection, tone adjustment, cross-source reasoning) is an instruction in the system prompt, not a separate agent.
|
||||||
|
|
||||||
@@ -50,7 +50,6 @@ The advantage: the LLM sees everything at once. It doesn't need agent-to-agent c
|
|||||||
The only separate LLM call is the **Query Agent** — because it's user-initiated and synchronous. But it uses the same system prompt and context. It's the same "person," just responding to a question instead of proactively enhancing the feed.
|
The only separate LLM call is the **Query Agent** — because it's user-initiated and synchronous. But it uses the same system prompt and context. It's the same "person," just responding to a question instead of proactively enhancing the feed.
|
||||||
|
|
||||||
Everything else is either:
|
Everything else is either:
|
||||||
|
|
||||||
- **Rule-based post-processors** — pure functions, no LLM, run on every refresh
|
- **Rule-based post-processors** — pure functions, no LLM, run on every refresh
|
||||||
- **The single LLM harness** — runs periodically, produces cached `FeedEnhancement`
|
- **The single LLM harness** — runs periodically, produces cached `FeedEnhancement`
|
||||||
- **Background jobs** — daily summary compression, weekly pattern discovery
|
- **Background jobs** — daily summary compression, weekly pattern discovery
|
||||||
@@ -58,7 +57,7 @@ Everything else is either:
|
|||||||
### Component categories
|
### Component categories
|
||||||
|
|
||||||
| Component | What it is | Examples |
|
| Component | What it is | Examples |
|
||||||
| ------------------------------ | ----------------------------------------- | --------------------------------------------------------------------- |
|
|---|---|---|
|
||||||
| **FeedSource nodes** | Graph participants that produce items | Briefing, Preparation, Anomaly Detection, Follow-up, Social Awareness |
|
| **FeedSource nodes** | Graph participants that produce items | Briefing, Preparation, Anomaly Detection, Follow-up, Social Awareness |
|
||||||
| **Rule-based post-processors** | Pure functions that rerank/filter/group | TimeOfDay, CalendarGrouping, Deduplication, UserAffinity |
|
| **Rule-based post-processors** | Pure functions that rerank/filter/group | TimeOfDay, CalendarGrouping, Deduplication, UserAffinity |
|
||||||
| **LLM enhancement harness** | Single background LLM call, cached output | Card rewriting, cross-source synthesis, tone, narrative arcs |
|
| **LLM enhancement harness** | Single background LLM call, cached output | Card rewriting, cross-source synthesis, tone, narrative arcs |
|
||||||
@@ -72,7 +71,7 @@ The LLM harness and post-processors need a unified view of the user's world: cur
|
|||||||
|
|
||||||
`AgentContext` is **not** on the engine. The engine's job is source orchestration — running sources in dependency order, accumulating context, collecting items. It shouldn't know about user preferences, conversation history, or feed snapshots. Those are separate concerns.
|
`AgentContext` is **not** on the engine. The engine's job is source orchestration — running sources in dependency order, accumulating context, collecting items. It shouldn't know about user preferences, conversation history, or feed snapshots. Those are separate concerns.
|
||||||
|
|
||||||
`AgentContext` is a separate object that _reads from_ the engine and composes its output with other data stores:
|
`AgentContext` is a separate object that *reads from* the engine and composes its output with other data stores:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface AgentContext {
|
interface AgentContext {
|
||||||
@@ -143,7 +142,7 @@ interface FeedEnhancement {
|
|||||||
annotations: Record<string, string>
|
annotations: Record<string, string>
|
||||||
|
|
||||||
/** Items to group together with a summary card */
|
/** Items to group together with a summary card */
|
||||||
groups: Array<{ itemIds: string[]; summary: string }>
|
groups: Array<{ itemIds: string[], summary: string }>
|
||||||
|
|
||||||
/** Item IDs to suppress or deprioritize */
|
/** Item IDs to suppress or deprioritize */
|
||||||
suppress: string[]
|
suppress: string[]
|
||||||
@@ -186,7 +185,6 @@ These run on every refresh. Fast, deterministic, and cover most of the ranking q
|
|||||||
**Anomaly detection.** Compare event start times against the user's historical distribution. A 6am meeting when the user never has meetings before 9am is a statistical outlier — flag it.
|
**Anomaly detection.** Compare event start times against the user's historical distribution. A 6am meeting when the user never has meetings before 9am is a statistical outlier — flag it.
|
||||||
|
|
||||||
**User affinity scoring.** Track implicit signals per source type per time-of-day bucket:
|
**User affinity scoring.** Track implicit signals per source type per time-of-day bucket:
|
||||||
|
|
||||||
- Dismissals: user swipes away weather cards → decay affinity for weather
|
- Dismissals: user swipes away weather cards → decay affinity for weather
|
||||||
- Taps: user taps calendar items frequently → boost affinity for calendar
|
- Taps: user taps calendar items frequently → boost affinity for calendar
|
||||||
- Dwell time: user reads TfL alerts carefully → boost
|
- Dwell time: user reads TfL alerts carefully → boost
|
||||||
@@ -311,7 +309,7 @@ There are three layers:
|
|||||||
|
|
||||||
None of these have `if` statements. The LLM reads the feed, reads the user's memory, and decides what to say. Add a new source (Spotify, email, tasks) and the LLM automatically incorporates it — no new behavior code needed.
|
None of these have `if` statements. The LLM reads the feed, reads the user's memory, and decides what to say. Add a new source (Spotify, email, tasks) and the LLM automatically incorporates it — no new behavior code needed.
|
||||||
|
|
||||||
**Infrastructure (plumbing needed, but logic is emergent).** These need tables, APIs, and background jobs. But the _decision-making_ — what to extract, when to surface, how to phrase — is all LLM.
|
**Infrastructure (plumbing needed, but logic is emergent).** These need tables, APIs, and background jobs. But the *decision-making* — what to extract, when to surface, how to phrase — is all LLM.
|
||||||
|
|
||||||
- Gentle Follow-up — needs: extraction pipeline after each conversation turn, `commitments` table. The LLM decides what counts as a commitment and when to remind.
|
- Gentle Follow-up — needs: extraction pipeline after each conversation turn, `commitments` table. The LLM decides what counts as a commitment and when to remind.
|
||||||
- Memory — needs: `memories` table, read/write API. The LLM decides what to remember and how to use it.
|
- Memory — needs: `memories` table, read/write API. The LLM decides what to remember and how to use it.
|
||||||
@@ -323,7 +321,7 @@ None of these have `if` statements. The LLM reads the feed, reads the user's mem
|
|||||||
- Delegation — needs: confirmation flow, write-back infrastructure. The LLM decides what the user wants done.
|
- Delegation — needs: confirmation flow, write-back infrastructure. The LLM decides what the user wants done.
|
||||||
- Financial Awareness — needs: `financial_events` table, email extraction. The LLM decides what financial events matter.
|
- Financial Awareness — needs: `financial_events` table, email extraction. The LLM decides what financial events matter.
|
||||||
|
|
||||||
**Hardcoded rules (fast path, must be deterministic).** These run on every refresh in <10ms. They _should_ be rules because they need to be fast and predictable.
|
**Hardcoded rules (fast path, must be deterministic).** These run on every refresh in <10ms. They *should* be rules because they need to be fast and predictable.
|
||||||
|
|
||||||
- User affinity scoring — decay/boost math on tap/dismiss events
|
- User affinity scoring — decay/boost math on tap/dismiss events
|
||||||
- Deduplication — title + time matching across sources
|
- Deduplication — title + time matching across sources
|
||||||
@@ -421,7 +419,10 @@ class EnhancementManager {
|
|||||||
private lastInputHash: string | null = null
|
private lastInputHash: string | null = null
|
||||||
private running = false
|
private running = false
|
||||||
|
|
||||||
async enhance(items: FeedItem[], context: AgentContext): Promise<FeedEnhancement> {
|
async enhance(
|
||||||
|
items: FeedItem[],
|
||||||
|
context: AgentContext,
|
||||||
|
): Promise<FeedEnhancement> {
|
||||||
const hash = computeHash(items, context)
|
const hash = computeHash(items, context)
|
||||||
|
|
||||||
// Nothing changed — return cache
|
// Nothing changed — return cache
|
||||||
@@ -437,14 +438,12 @@ class EnhancementManager {
|
|||||||
// Run in background, update cache when done
|
// Run in background, update cache when done
|
||||||
this.running = true
|
this.running = true
|
||||||
this.runHarness(items, context, hash)
|
this.runHarness(items, context, hash)
|
||||||
.then((enhancement) => {
|
.then(enhancement => {
|
||||||
this.cache = enhancement
|
this.cache = enhancement
|
||||||
this.lastInputHash = hash
|
this.lastInputHash = hash
|
||||||
this.notifySubscribers(enhancement)
|
this.notifySubscribers(enhancement)
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => { this.running = false })
|
||||||
this.running = false
|
|
||||||
})
|
|
||||||
|
|
||||||
// Return stale cache immediately
|
// Return stale cache immediately
|
||||||
return this.cache ?? emptyEnhancement()
|
return this.cache ?? emptyEnhancement()
|
||||||
@@ -523,7 +522,7 @@ These are `FeedSource` nodes that depend on calendar, tasks, weather, and other
|
|||||||
|
|
||||||
#### Anticipatory Logistics
|
#### Anticipatory Logistics
|
||||||
|
|
||||||
Works backward from events to tell you what you need to _do_ to be ready.
|
Works backward from events to tell you what you need to *do* to be ready.
|
||||||
|
|
||||||
- Flight at 6am → "You need to leave by 4am, which means waking at 3:30. I'd suggest packing tonight."
|
- Flight at 6am → "You need to leave by 4am, which means waking at 3:30. I'd suggest packing tonight."
|
||||||
- Dinner at a new restaurant → "It's a 25-minute walk or 8-minute Uber. Street parking is difficult — there's a car park on the next street."
|
- Dinner at a new restaurant → "It's a 25-minute walk or 8-minute Uber. Street parking is difficult — there's a car park on the next street."
|
||||||
@@ -580,7 +579,7 @@ Tracks loose ends — things you said but never wrote down as tasks.
|
|||||||
- "You told James you'd review his PR — it's been 3 days"
|
- "You told James you'd review his PR — it's been 3 days"
|
||||||
- "You promised to call your mom this weekend"
|
- "You promised to call your mom this weekend"
|
||||||
|
|
||||||
The key difference from task tracking: this catches things that fell through the cracks _because_ they were never formalized.
|
The key difference from task tracking: this catches things that fell through the cracks *because* they were never formalized.
|
||||||
|
|
||||||
**How intent extraction works:**
|
**How intent extraction works:**
|
||||||
|
|
||||||
@@ -615,14 +614,12 @@ Long-term memory of interactions and preferences. Feeds into every other agent.
|
|||||||
A persistent profile that builds over time. Not an agent itself — a system that makes every other agent smarter.
|
A persistent profile that builds over time. Not an agent itself — a system that makes every other agent smarter.
|
||||||
|
|
||||||
Learns from:
|
Learns from:
|
||||||
|
|
||||||
- Explicit statements: "I prefer morning meetings"
|
- Explicit statements: "I prefer morning meetings"
|
||||||
- Implicit behavior: user always dismisses evening suggestions
|
- Implicit behavior: user always dismisses evening suggestions
|
||||||
- Feedback: user rates suggestions as helpful/not
|
- Feedback: user rates suggestions as helpful/not
|
||||||
- Cross-source patterns: always books aisle seats, always picks the cheaper option
|
- Cross-source patterns: always books aisle seats, always picks the cheaper option
|
||||||
|
|
||||||
Used by:
|
Used by:
|
||||||
|
|
||||||
- Proactive Agent suggests restaurants the user would actually like
|
- Proactive Agent suggests restaurants the user would actually like
|
||||||
- Delegation Agent books the right kind of hotel room
|
- Delegation Agent books the right kind of hotel room
|
||||||
- Summary Agent uses the user's preferred level of detail
|
- Summary Agent uses the user's preferred level of detail
|
||||||
@@ -654,20 +651,17 @@ interface DailySummary {
|
|||||||
date: string
|
date: string
|
||||||
feedCheckTimes: string[] // when the user opened the feed
|
feedCheckTimes: string[] // when the user opened the feed
|
||||||
itemTypeCounts: Record<string, number> // how many of each type appeared
|
itemTypeCounts: Record<string, number> // how many of each type appeared
|
||||||
interactions: Array<{
|
interactions: Array<{ // what the user tapped/dismissed
|
||||||
// what the user tapped/dismissed
|
|
||||||
itemType: string
|
itemType: string
|
||||||
action: "tap" | "dismiss" | "dwell"
|
action: "tap" | "dismiss" | "dwell"
|
||||||
time: string
|
time: string
|
||||||
}>
|
}>
|
||||||
locations: Array<{
|
locations: Array<{ // where the user was throughout the day
|
||||||
// where the user was throughout the day
|
|
||||||
lat: number
|
lat: number
|
||||||
lng: number
|
lng: number
|
||||||
time: string
|
time: string
|
||||||
}>
|
}>
|
||||||
calendarSummary: Array<{
|
calendarSummary: Array<{ // what events happened
|
||||||
// what events happened
|
|
||||||
title: string
|
title: string
|
||||||
startTime: string
|
startTime: string
|
||||||
endTime: string
|
endTime: string
|
||||||
@@ -691,7 +685,7 @@ interface DiscoveredPattern {
|
|||||||
/** When this pattern is relevant */
|
/** When this pattern is relevant */
|
||||||
relevance: {
|
relevance: {
|
||||||
daysOfWeek?: number[]
|
daysOfWeek?: number[]
|
||||||
timeRange?: { start: string; end: string }
|
timeRange?: { start: string, end: string }
|
||||||
conditions?: string[]
|
conditions?: string[]
|
||||||
}
|
}
|
||||||
/** How this should affect the feed */
|
/** How this should affect the feed */
|
||||||
@@ -723,9 +717,9 @@ Maintains awareness of relationships and surfaces timely nudges.
|
|||||||
|
|
||||||
Needs: contacts with birthday/anniversary data, calendar history for meeting frequency, email/message signals, optionally social media.
|
Needs: contacts with birthday/anniversary data, calendar history for meeting frequency, email/message signals, optionally social media.
|
||||||
|
|
||||||
This is what makes an assistant feel like it _cares_. Most tools are transactional. This one remembers the people in your life.
|
This is what makes an assistant feel like it *cares*. Most tools are transactional. This one remembers the people in your life.
|
||||||
|
|
||||||
Beyond frequency, the assistant can understand relationship _dynamics_:
|
Beyond frequency, the assistant can understand relationship *dynamics*:
|
||||||
|
|
||||||
- "You and Sarah always have productive meetings. You and Alex tend to go off-track — maybe set a tighter agenda."
|
- "You and Sarah always have productive meetings. You and Alex tend to go off-track — maybe set a tighter agenda."
|
||||||
- "You've cancelled on Tom three times — he might be feeling deprioritized."
|
- "You've cancelled on Tom three times — he might be feeling deprioritized."
|
||||||
@@ -791,7 +785,7 @@ This is where the source graph pays off. All the data is already there — the a
|
|||||||
|
|
||||||
#### Tone & Timing
|
#### Tone & Timing
|
||||||
|
|
||||||
Controls _when_ and _how_ information is delivered. The difference between useful and annoying.
|
Controls *when* and *how* information is delivered. The difference between useful and annoying.
|
||||||
|
|
||||||
- Bad news before morning coffee? Hold it.
|
- Bad news before morning coffee? Hold it.
|
||||||
- Three notifications in a row? Batch them.
|
- Three notifications in a row? Batch them.
|
||||||
@@ -855,7 +849,6 @@ The primary interface. This isn't a feed query tool — it's the person you talk
|
|||||||
The user should be able to ask AELIS anything they'd ask a knowledgeable friend. Some questions are about their data. Most aren't.
|
The user should be able to ask AELIS anything they'd ask a knowledgeable friend. Some questions are about their data. Most aren't.
|
||||||
|
|
||||||
**About their life (reads from the source graph):**
|
**About their life (reads from the source graph):**
|
||||||
|
|
||||||
- "What's on my calendar tomorrow?"
|
- "What's on my calendar tomorrow?"
|
||||||
- "When's my next flight?"
|
- "When's my next flight?"
|
||||||
- "Do I have any conflicts this week?"
|
- "Do I have any conflicts this week?"
|
||||||
@@ -863,7 +856,6 @@ The user should be able to ask AELIS anything they'd ask a knowledgeable friend.
|
|||||||
- "Tell me more about this" (anchored to a feed item)
|
- "Tell me more about this" (anchored to a feed item)
|
||||||
|
|
||||||
**About the world (falls through to web search):**
|
**About the world (falls through to web search):**
|
||||||
|
|
||||||
- "How do I unclog a drain?"
|
- "How do I unclog a drain?"
|
||||||
- "What should I make with chicken and broccoli?"
|
- "What should I make with chicken and broccoli?"
|
||||||
- "What's the best way to get from King's Cross to Heathrow?"
|
- "What's the best way to get from King's Cross to Heathrow?"
|
||||||
@@ -872,7 +864,6 @@ The user should be able to ask AELIS anything they'd ask a knowledgeable friend.
|
|||||||
- "What are some good date night restaurants in Shoreditch?"
|
- "What are some good date night restaurants in Shoreditch?"
|
||||||
|
|
||||||
**Contextual blend (graph + web):**
|
**Contextual blend (graph + web):**
|
||||||
|
|
||||||
- "What's the dress code for The Ivy?" (calendar shows dinner there tonight)
|
- "What's the dress code for The Ivy?" (calendar shows dinner there tonight)
|
||||||
- "Will I need an umbrella?" (location + weather, but could also web-search venue for indoor/outdoor)
|
- "Will I need an umbrella?" (location + weather, but could also web-search venue for indoor/outdoor)
|
||||||
- "What should I know before my meeting with Acme Corp?" (calendar + web search for company info)
|
- "What should I know before my meeting with Acme Corp?" (calendar + web search for company info)
|
||||||
@@ -888,12 +879,10 @@ This is also where intent extraction happens for the Gentle Follow-up Agent. Eve
|
|||||||
The backbone for general knowledge. Makes AELIS a person you can ask things, not just a dashboard you look at.
|
The backbone for general knowledge. Makes AELIS a person you can ask things, not just a dashboard you look at.
|
||||||
|
|
||||||
**Reactive (user asks):**
|
**Reactive (user asks):**
|
||||||
|
|
||||||
- Recipe ideas, how-to questions, factual lookups, recommendations
|
- Recipe ideas, how-to questions, factual lookups, recommendations
|
||||||
- Anything the source graph can't answer
|
- Anything the source graph can't answer
|
||||||
|
|
||||||
**Proactive (agents trigger):**
|
**Proactive (agents trigger):**
|
||||||
|
|
||||||
- Contextual Preparation enriches calendar events: venue info, attendee backgrounds, parking
|
- Contextual Preparation enriches calendar events: venue info, attendee backgrounds, parking
|
||||||
- Feed shows a concert → pre-fetches setlist, venue details
|
- Feed shows a concert → pre-fetches setlist, venue details
|
||||||
- Ambient Context checks for disruptions, closures, news
|
- Ambient Context checks for disruptions, closures, news
|
||||||
@@ -960,7 +949,7 @@ Handles tasks the user delegates via natural language.
|
|||||||
|
|
||||||
Requires write access to sources. Confirmation UX for anything destructive or costly.
|
Requires write access to sources. Confirmation UX for anything destructive or costly.
|
||||||
|
|
||||||
**Implementation:** Extends the Query Agent. When the LLM determines the user wants to _do_ something (not just ask), it calls a delegation tool with structured output: `{ action: "create_reminder" | "schedule_meeting" | "add_task", params: {...} }`. The backend maps this to `executeAction()` on the relevant source. For "find a time that works for both me and Sarah," the agent queries both calendars (requires Sarah to be a known contact with calendar access — or the agent asks the user to share availability). All write actions go through a confirmation step: the backend sends a `delegation.confirm` notification with the proposed action, and the client shows a confirmation UI. The user approves or modifies before execution. Store delegation history for the Follow-up Agent.
|
**Implementation:** Extends the Query Agent. When the LLM determines the user wants to *do* something (not just ask), it calls a delegation tool with structured output: `{ action: "create_reminder" | "schedule_meeting" | "add_task", params: {...} }`. The backend maps this to `executeAction()` on the relevant source. For "find a time that works for both me and Sarah," the agent queries both calendars (requires Sarah to be a known contact with calendar access — or the agent asks the user to share availability). All write actions go through a confirmation step: the backend sends a `delegation.confirm` notification with the proposed action, and the client shows a confirmation UI. The user approves or modifies before execution. Store delegation history for the Follow-up Agent.
|
||||||
|
|
||||||
#### Actions
|
#### Actions
|
||||||
|
|
||||||
|
|||||||
@@ -238,15 +238,20 @@ The user never waits for the LLM. They see the feed instantly with the previous
|
|||||||
The harness serializes items with their unfilled slots into a single prompt. Items without slots are excluded. The LLM sees everything at once and fills whatever slots are relevant.
|
The harness serializes items with their unfilled slots into a single prompt. Items without slots are excluded. The LLM sees everything at once and fills whatever slots are relevant.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
function buildHarnessInput(items: FeedItem[], context: AgentContext): HarnessInput {
|
function buildHarnessInput(
|
||||||
|
items: FeedItem[],
|
||||||
|
context: AgentContext,
|
||||||
|
): HarnessInput {
|
||||||
const itemsWithSlots = items
|
const itemsWithSlots = items
|
||||||
.filter((item) => item.slots && Object.keys(item.slots).length > 0)
|
.filter(item => item.slots && Object.keys(item.slots).length > 0)
|
||||||
.map((item) => ({
|
.map(item => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
type: item.type,
|
type: item.type,
|
||||||
data: item.data,
|
data: item.data,
|
||||||
slots: Object.fromEntries(
|
slots: Object.fromEntries(
|
||||||
Object.entries(item.slots!).map(([name, slot]) => [name, slot.description]),
|
Object.entries(item.slots!).map(
|
||||||
|
([name, slot]) => [name, slot.description]
|
||||||
|
)
|
||||||
),
|
),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@@ -275,11 +280,7 @@ The LLM sees:
|
|||||||
{
|
{
|
||||||
"id": "calendar-event-456",
|
"id": "calendar-event-456",
|
||||||
"type": "calendar-event",
|
"type": "calendar-event",
|
||||||
"data": {
|
"data": { "title": "Dinner at The Ivy", "startTime": "19:00", "location": "The Ivy, West St" },
|
||||||
"title": "Dinner at The Ivy",
|
|
||||||
"startTime": "19:00",
|
|
||||||
"location": "The Ivy, West St"
|
|
||||||
},
|
|
||||||
"slots": {
|
"slots": {
|
||||||
"context": "Background on this event, attendees, or previous meetings with these people",
|
"context": "Background on this event, attendees, or previous meetings with these people",
|
||||||
"logistics": "Travel time, parking, directions to the venue",
|
"logistics": "Travel time, parking, directions to the venue",
|
||||||
@@ -314,10 +315,7 @@ A flat map of item ID → slot name → text content. Slots left null are unfill
|
|||||||
"id": "briefing-morning",
|
"id": "briefing-morning",
|
||||||
"type": "briefing",
|
"type": "briefing",
|
||||||
"data": {},
|
"data": {},
|
||||||
"ui": {
|
"ui": { "component": "Text", "props": { "text": "Light afternoon — just your dinner at 7. Rain clears by then." } }
|
||||||
"component": "Text",
|
|
||||||
"props": { "text": "Light afternoon — just your dinner at 7. Rain clears by then." }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"suppress": [],
|
"suppress": [],
|
||||||
@@ -335,7 +333,10 @@ class EnhancementManager {
|
|||||||
private lastInputHash: string | null = null
|
private lastInputHash: string | null = null
|
||||||
private running = false
|
private running = false
|
||||||
|
|
||||||
async enhance(items: FeedItem[], context: AgentContext): Promise<EnhancementResult> {
|
async enhance(
|
||||||
|
items: FeedItem[],
|
||||||
|
context: AgentContext,
|
||||||
|
): Promise<EnhancementResult> {
|
||||||
const hash = computeHash(items, context)
|
const hash = computeHash(items, context)
|
||||||
|
|
||||||
if (hash === this.lastInputHash && this.cache) {
|
if (hash === this.lastInputHash && this.cache) {
|
||||||
@@ -348,14 +349,12 @@ class EnhancementManager {
|
|||||||
|
|
||||||
this.running = true
|
this.running = true
|
||||||
this.runHarness(items, context)
|
this.runHarness(items, context)
|
||||||
.then((result) => {
|
.then(result => {
|
||||||
this.cache = result
|
this.cache = result
|
||||||
this.lastInputHash = hash
|
this.lastInputHash = hash
|
||||||
this.notifySubscribers(result)
|
this.notifySubscribers(result)
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => { this.running = false })
|
||||||
this.running = false
|
|
||||||
})
|
|
||||||
|
|
||||||
return this.cache ?? emptyResult()
|
return this.cache ?? emptyResult()
|
||||||
}
|
}
|
||||||
@@ -374,8 +373,11 @@ interface EnhancementResult {
|
|||||||
After the harness runs, the engine merges slot fills into items:
|
After the harness runs, the engine merges slot fills into items:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
function mergeEnhancement(items: FeedItem[], result: EnhancementResult): FeedItem[] {
|
function mergeEnhancement(
|
||||||
return items.map((item) => {
|
items: FeedItem[],
|
||||||
|
result: EnhancementResult,
|
||||||
|
): FeedItem[] {
|
||||||
|
return items.map(item => {
|
||||||
const fills = result.slotFills[item.id]
|
const fills = result.slotFills[item.id]
|
||||||
if (!fills || !item.slots) return item
|
if (!fills || !item.slots) return item
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ The backend uses a raw `pg` Pool for Better Auth and has no ORM. We need a persi
|
|||||||
A `user_sources` table stores per-user source state:
|
A `user_sources` table stores per-user source state:
|
||||||
|
|
||||||
| Column | Type | Description |
|
| Column | Type | Description |
|
||||||
| ------------- | --------------------- | -------------------------------------------------------------- |
|
| ------------ | ------------------------ | ------------------------------------------------------------ |
|
||||||
| `id` | `uuid` PK | Row ID |
|
| `id` | `uuid` PK | Row ID |
|
||||||
| `user_id` | `text` FK → `user.id` | Owner |
|
| `user_id` | `text` FK → `user.id` | Owner |
|
||||||
| `source_id` | `text` | Source identifier (e.g., `aelis.tfl`, `aelis.weather`) |
|
| `source_id` | `text` | Source identifier (e.g., `aelis.tfl`, `aelis.weather`) |
|
||||||
@@ -51,7 +51,7 @@ A `user_sources` table stores per-user source state:
|
|||||||
When a new user is created, seed `user_sources` rows for default sources:
|
When a new user is created, seed `user_sources` rows for default sources:
|
||||||
|
|
||||||
| Source | Default config |
|
| Source | Default config |
|
||||||
| ---------------- | ----------------------------------------------------------- |
|
| ------------------ | --------------------------------------------------------------- |
|
||||||
| `aelis.location` | `{}` |
|
| `aelis.location` | `{}` |
|
||||||
| `aelis.weather` | `{ "units": "metric", "hourlyLimit": 12, "dailyLimit": 7 }` |
|
| `aelis.weather` | `{ "units": "metric", "hourlyLimit": 12, "dailyLimit": 7 }` |
|
||||||
| `aelis.tfl` | `{ "lines": <all default lines> }` |
|
| `aelis.tfl` | `{ "lines": <all default lines> }` |
|
||||||
@@ -67,22 +67,16 @@ Each provider receives the Drizzle DB instance and queries `user_sources` intern
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class TflSourceProvider implements FeedSourceProvider {
|
class TflSourceProvider implements FeedSourceProvider {
|
||||||
constructor(
|
constructor(private db: DrizzleDb, private apiKey: string) {}
|
||||||
private db: DrizzleDb,
|
|
||||||
private apiKey: string,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async feedSourceForUser(userId: string): Promise<TflSource> {
|
async feedSourceForUser(userId: string): Promise<TflSource> {
|
||||||
const row = await this.db
|
const row = await this.db.select()
|
||||||
.select()
|
|
||||||
.from(userSources)
|
.from(userSources)
|
||||||
.where(
|
.where(and(
|
||||||
and(
|
|
||||||
eq(userSources.userId, userId),
|
eq(userSources.userId, userId),
|
||||||
eq(userSources.sourceId, "aelis.tfl"),
|
eq(userSources.sourceId, "aelis.tfl"),
|
||||||
eq(userSources.enabled, true),
|
eq(userSources.enabled, true),
|
||||||
),
|
))
|
||||||
)
|
|
||||||
.limit(1)
|
.limit(1)
|
||||||
|
|
||||||
if (!row[0]) {
|
if (!row[0]) {
|
||||||
@@ -216,19 +210,16 @@ _`feed-source-provider.ts`, `user-session-manager.ts`, `engine/http.ts`, and `lo
|
|||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
**Add:**
|
**Add:**
|
||||||
|
|
||||||
- `drizzle-orm`
|
- `drizzle-orm`
|
||||||
- `drizzle-kit` (dev)
|
- `drizzle-kit` (dev)
|
||||||
|
|
||||||
**Remove:**
|
**Remove:**
|
||||||
|
|
||||||
- `pg`
|
- `pg`
|
||||||
- `@types/pg` (dev)
|
- `@types/pg` (dev)
|
||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
|
|
||||||
**Add to `.env.example`:**
|
**Add to `.env.example`:**
|
||||||
|
|
||||||
- `CREDENTIALS_ENCRYPTION_KEY` — 32-byte hex or base64 key for AES-256-GCM
|
- `CREDENTIALS_ENCRYPTION_KEY` — 32-byte hex or base64 key for AES-256-GCM
|
||||||
|
|
||||||
## Open Questions (Deferred)
|
## Open Questions (Deferred)
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ Source IDs use reverse domain notation. Built-in sources use `aelis.<name>`. Thi
|
|||||||
Action IDs are descriptive verb-noun pairs in kebab-case, scoped to their source. The globally unique form is `<sourceId>/<actionId>`.
|
Action IDs are descriptive verb-noun pairs in kebab-case, scoped to their source. The globally unique form is `<sourceId>/<actionId>`.
|
||||||
|
|
||||||
| Source ID | Action IDs |
|
| Source ID | Action IDs |
|
||||||
| ---------------- | -------------------------------------------------------------- |
|
| --------------- | -------------------------------------------------------------- |
|
||||||
| `aelis.location` | `update-location` (migrated from `pushLocation()`) |
|
| `aelis.location` | `update-location` (migrated from `pushLocation()`) |
|
||||||
| `aelis.tfl` | `set-lines-of-interest` (migrated from `setLinesOfInterest()`) |
|
| `aelis.tfl` | `set-lines-of-interest` (migrated from `setLinesOfInterest()`) |
|
||||||
| `aelis.weather` | _(none)_ |
|
| `aelis.weather` | _(none)_ |
|
||||||
@@ -241,16 +241,8 @@ class SpotifySource implements FeedSource<SpotifyFeedItem> {
|
|||||||
type: "View",
|
type: "View",
|
||||||
className: "flex-1",
|
className: "flex-1",
|
||||||
children: [
|
children: [
|
||||||
{
|
{ type: "Text", className: "font-semibold text-black dark:text-white", text: track.name },
|
||||||
type: "Text",
|
{ type: "Text", className: "text-sm text-gray-500 dark:text-gray-400", text: track.artist },
|
||||||
className: "font-semibold text-black dark:text-white",
|
|
||||||
text: track.name,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "Text",
|
|
||||||
className: "text-sm text-gray-500 dark:text-gray-400",
|
|
||||||
text: track.artist,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
11
package.json
11
package.json
@@ -11,23 +11,16 @@
|
|||||||
"lint": "oxlint .",
|
"lint": "oxlint .",
|
||||||
"lint:fix": "oxlint --fix .",
|
"lint:fix": "oxlint --fix .",
|
||||||
"format": "oxfmt --write .",
|
"format": "oxfmt --write .",
|
||||||
"format:check": "oxfmt --check .",
|
"format:check": "oxfmt --check ."
|
||||||
"prepare": "husky"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@json-render/core": "^0.12.1",
|
"@json-render/core": "^0.12.1",
|
||||||
"@nym.sh/jrx": "^0.2.0",
|
"@nym.sh/jrx": "^0.2.0",
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
"@typescript/native-preview": "^7.0.0-dev.20260412.1",
|
|
||||||
"husky": "^9.1.7",
|
|
||||||
"lint-staged": "^16.4.0",
|
|
||||||
"oxfmt": "^0.24.0",
|
"oxfmt": "^0.24.0",
|
||||||
"oxlint": "^1.39.0"
|
"oxlint": "^1.39.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "^6"
|
"typescript": "^5"
|
||||||
},
|
|
||||||
"lint-staged": {
|
|
||||||
"*.{ts,tsx,js,jsx,json,css,md}": "oxfmt --write"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "bun test ."
|
"test": "bun test ."
|
||||||
},
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@nym.sh/jrx": "*",
|
||||||
|
"@json-render/core": "*"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@standard-schema/spec": "^1.1.0"
|
"@standard-schema/spec": "^1.1.0"
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@json-render/core": "*",
|
|
||||||
"@nym.sh/jrx": "*"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
packages/aelis-data-source-weatherkit/.env.example
Normal file
4
packages/aelis-data-source-weatherkit/.env.example
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
WEATHERKIT_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
|
||||||
|
WEATHERKIT_KEY_ID=ABC123DEFG
|
||||||
|
WEATHERKIT_TEAM_ID=TEAM123456
|
||||||
|
WEATHERKIT_SERVICE_ID=com.example.weatherkit.test
|
||||||
58
packages/aelis-data-source-weatherkit/README.md
Normal file
58
packages/aelis-data-source-weatherkit/README.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# @aelis/data-source-weatherkit
|
||||||
|
|
||||||
|
Weather data source using Apple WeatherKit REST API.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { WeatherKitDataSource, Units } from "@aelis/data-source-weatherkit"
|
||||||
|
|
||||||
|
const dataSource = new WeatherKitDataSource({
|
||||||
|
credentials: {
|
||||||
|
privateKey: "-----BEGIN PRIVATE KEY-----\n...",
|
||||||
|
keyId: "ABC123",
|
||||||
|
teamId: "DEF456",
|
||||||
|
serviceId: "com.example.weatherkit",
|
||||||
|
},
|
||||||
|
hourlyLimit: 12, // optional, default: 12
|
||||||
|
dailyLimit: 7, // optional, default: 7
|
||||||
|
})
|
||||||
|
|
||||||
|
const items = await dataSource.query(context, {
|
||||||
|
units: Units.metric, // or Units.imperial
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Feed Items
|
||||||
|
|
||||||
|
The data source returns four types of feed items:
|
||||||
|
|
||||||
|
| Type | Description |
|
||||||
|
| ----------------- | -------------------------- |
|
||||||
|
| `weather-current` | Current weather conditions |
|
||||||
|
| `weather-hourly` | Hourly forecast |
|
||||||
|
| `weather-daily` | Daily forecast |
|
||||||
|
| `weather-alert` | Weather alerts |
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
Base priorities are adjusted based on weather conditions:
|
||||||
|
|
||||||
|
- Severe conditions (tornado, hurricane, blizzard, etc.): +0.3
|
||||||
|
- Moderate conditions (thunderstorm, heavy rain, etc.): +0.15
|
||||||
|
- Alert severity: extreme=1.0, severe=0.9, moderate=0.75, minor=0.7
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
WeatherKit requires Apple Developer credentials. Generate a private key in the Apple Developer portal under Certificates, Identifiers & Profiles > Keys.
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
API responses are validated using [arktype](https://arktype.io) schemas.
|
||||||
|
|
||||||
|
## Generating Test Fixtures
|
||||||
|
|
||||||
|
To regenerate fixture data from the real API:
|
||||||
|
|
||||||
|
1. Create a `.env` file with your credentials (see `.env.example`)
|
||||||
|
2. Run `bun run scripts/generate-fixtures.ts`
|
||||||
6457
packages/aelis-data-source-weatherkit/fixtures/san-francisco.json
Normal file
6457
packages/aelis-data-source-weatherkit/fixtures/san-francisco.json
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user