Compare commits
3 commits
TEST_AUTOM
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 884ec8f791 | |||
| 1446cc33e4 | |||
| 9bca425f11 |
68 changed files with 247 additions and 14327 deletions
|
|
@ -81,18 +81,7 @@
|
|||
"Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo && npx tsc --noEmit -p tests 2>&1 | tail -5; echo \"tsc_exit=$?\"; bun run test:e2e > /tmp/e2e_run9.log 2>&1; echo \"exit=$?\" >> /tmp/e2e_run9.log)",
|
||||
"Shell(DEBUG=pw:browser npx playwright test tests/specs/smoke.spec.ts 2 >& 1)",
|
||||
"Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo && git diff product_to_sku_c1 -- apps/user-ui/hooks/cart-query-hooks.tsx apps/user-ui/hooks/useUploadToObjectStore.ts apps/user-ui/eas.json apps/user-ui/'(drawer)' 2>/dev/null; git diff product_to_sku_c1 -- \"apps/user-ui/app/(drawer)/(tabs)/me/addresses/index.tsx\" \"apps/user-ui/app/(drawer)/(tabs)/me/my-orders/index.tsx\" | head -160)",
|
||||
"Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo/packages/db_helper_sqlite && npx tsc --noEmit 2>&1 | tail -8; echo \"sqlite_exit=$?\"; echo \"=== user-ui ===\"; cd /Users/mohammedshafiuddin/WebDev/freshyo/apps/user-ui && npx tsc --noEmit 2>&1 | tee /tmp/uui_tsc.txt | tail -5; echo \"userui_errors=$(grep -cE 'error TS' /tmp/uui_tsc.txt)\")",
|
||||
"Shell(/.maestro/bin/maestro:*)",
|
||||
"Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo && adb shell am force-stop in.freshyo.app; adb shell monkey -p in.freshyo.app -c android.intent.category.LAUNCHER 1 >/dev/null 2>&1; sleep 8; mkdir -p \"$COMMANDCODE_SCRATCHPAD\"; adb exec-out screencap -p > \"$COMMANDCODE_SCRATCHPAD/screen1.png\"; ls -la \"$COMMANDCODE_SCRATCHPAD/screen1.png\")",
|
||||
"Shell(adb:*)",
|
||||
"Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo && adb exec-out screencap -p > \"$COMMANDCODE_SCRATCHPAD/screen2.png\" && ls -la \"$COMMANDCODE_SCRATCHPAD/screen2.png\")",
|
||||
"Shell(bash e2e/run.sh flows/smoke.yaml 2 >& 1)",
|
||||
"Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo && \"$HOME/.maestro/bin/maestro\" hierarchy --platform android 2>/dev/null > \"$COMMANDCODE_SCRATCHPAD/hier.json\"; wc -c \"$COMMANDCODE_SCRATCHPAD/hier.json\"; echo \"=== occurrences ===\"; grep -o \"product-card\" \"$COMMANDCODE_SCRATCHPAD/hier.json\" | head -3; echo \"--- context around testID usages ---\"; grep -oE '\"(resource-id|content-desc|text|accessibilityText)\": \"[^\"]{0,40}\"' \"$COMMANDCODE_SCRATCHPAD/hier.json\" | sort | uniq -c | sort -rn | head -20)",
|
||||
"Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo && adb shell uiautomator dump /sdcard/ui.xml >/dev/null 2>&1; adb shell cat /sdcard/ui.xml > \"$COMMANDCODE_SCRATCHPAD/ui.xml\" 2>/dev/null; wc -c \"$COMMANDCODE_SCRATCHPAD/ui.xml\"; echo \"=== product-card? ===\"; grep -o \"product-card\" \"$COMMANDCODE_SCRATCHPAD/ui.xml\" | head -2; echo \"=== sample attrs ===\"; grep -oE 'content-desc=\"[^\"]{1,40}\"' \"$COMMANDCODE_SCRATCHPAD/ui.xml\" | sort -u | head -15; echo \"=== text sample ===\"; grep -oE 'text=\"[^\"]{2,40}\"' \"$COMMANDCODE_SCRATCHPAD/ui.xml\" | sort -u | head -20)",
|
||||
"Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo && adb shell am force-stop in.freshyo.app; adb shell monkey -p in.freshyo.app -c android.intent.category.LAUNCHER 1 >/dev/null 2>&1; sleep 16; adb shell uiautomator dump /sdcard/ui2.xml >/dev/null 2>&1; adb shell cat /sdcard/ui2.xml > \"$COMMANDCODE_SCRATCHPAD/ui2.xml\" 2>/dev/null; echo \"size: $(wc -c < \"$COMMANDCODE_SCRATCHPAD/ui2.xml\")\"; echo \"=== product-card occurrences ===\"; grep -c \"product-card\" \"$COMMANDCODE_SCRATCHPAD/ui2.xml\" || true; echo \"=== resource-id sample ===\"; grep -oE 'resource-id=\"[^\"]{1,50}\"' \"$COMMANDCODE_SCRATCHPAD/ui2.xml\" | sort -u | head -15; echo \"=== content-desc sample ===\"; grep -oE 'content-desc=\"[^\"]{2,40}\"' \"$COMMANDCODE_SCRATCHPAD/ui2.xml\" | sort -u | head -15)",
|
||||
"Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo && cat > \"$COMMANDCODE_SCRATCHPAD/probe2.yaml\" <<'YAML' appId: in.freshyo.app --- - assertVisible: id: \"product-card\" YAML \"$HOME/.maestro/bin/maestro\" test \"$COMMANDCODE_SCRATCHPAD/probe2.yaml\" --platform android 2>&1 | tail -6)",
|
||||
"Shell(bash e2e/run.sh flows/place-order.yaml 2 >& 1)",
|
||||
"Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo && ls ~/.maestro/tests/2026-09-14_154602/place-order/screen-hierarchy/ 2>/dev/null; F=$(ls ~/.maestro/tests/2026-09-14_154602/place-order/screen-hierarchy/*Me* 2>/dev/null | head -1); echo \"file: $F\"; grep -oE '\"(text|accessibilityText|resource-id)\": \"[^\"]{1,30}\"' \"$F\" 2>/dev/null | sort -u | head -40)"
|
||||
"Shell(cd /Users/mohammedshafiuddin/WebDev/freshyo/packages/db_helper_sqlite && npx tsc --noEmit 2>&1 | tail -8; echo \"sqlite_exit=$?\"; echo \"=== user-ui ===\"; cd /Users/mohammedshafiuddin/WebDev/freshyo/apps/user-ui && npx tsc --noEmit 2>&1 | tee /tmp/uui_tsc.txt | tail -5; echo \"userui_errors=$(grep -cE 'error TS' /tmp/uui_tsc.txt)\")"
|
||||
],
|
||||
"deny": [],
|
||||
"defaultMode": "default"
|
||||
|
|
|
|||
|
|
@ -124,12 +124,6 @@ er-ui/app/(drawer)/(tabs)/home/index.tsx, I want similar here") and expects the
|
|||
- Prefers that disruptive user-facing dialogs be reserved for genuinely important events: the OTA update prompt should NOT be shown for every update — only for a few crucial releases ("I don't want to show this for all the updates. Only a few updates are so important"), while routine updates apply silently in the background. Confidence: 0.7
|
||||
- Uses "quantity" loosely to refer to the pack size / unit notation on order items: he reported "we aren't showing quantity" about a row that already rendered the numeric count, then clarified "yeah, show the pack size" — so when he says a quantity isn't shown, check whether he actually means the unit/pack-size notation is missing. Confidence: 0.55
|
||||
- For new operational switches/flags, prefers a backend constant in the admin-editable constants store (CONST_KEYS + seed + exposed via essentialConsts, editable in Customize App) over build/publish-time config (e.g. an `expo.extra` flag in app.json) or hardcoding — chosen when offered the trade-off ("let's introduce a new constant"), because it can be changed remotely with no rebuild or republish. Confidence: 0.6
|
||||
- Dislikes long lists of CLI flags for supplying run-time/test values and asks for a "better way" ("isn't there a better way to supply the values"). Expects values supplied declaratively: non-secret defaults committed in a config file (e.g. Maestro `config.yaml` `env:` block), secrets in a gitignored `.env`-style file, and a thin wrapper/runner script wired to a single package-manager entry point (`bun run e2e`) so one short command runs everything — with extra flags still passable through. Secrets should never be passed inline on the command line or committed. Confidence: 0.7
|
||||
- When he doubts the current approach ("isn't there a better way"), expects the agent to actually research the tool's documented capabilities (check `--help`, official docs) before proposing alternatives, rather than answering from memory. Confidence: 0.6
|
||||
- For mobile app E2E testing, wants Android ONLY and never iOS — stated explicitly: "I want to test only on android. Never on ios." The test runner/harness should be wired so it can never target an iOS simulator (e.g., pin the Android package id and always pass `--platform android`), rather than auto-detecting the platform from booted devices. Confidence: 0.9
|
||||
- For React Native / Expo mobile E2E automation, prefers **Maestro** (not Detox/Appium), with its flow configs in a folder at the repo ROOT named `e2e/` — "I want test end to end test automation with maestro. have a folder at the root named e2e" — mirroring his `tests/`-at-root convention for Playwright. Expects the tool's own YAML workspace layout inside it (`config.yaml`, `flows/`, reusable `subflows/`), not per-app test dirs. Confidence: 0.85
|
||||
- Wants E2E flows to take the shortest realistic user path and skip unnecessary intermediate screens — e.g., add to the cart directly from the home product card's cart icon instead of opening the product-detail screen first ("don't open any product detail. Just click on the cart icon of any product, then go to the cart page and then place order"). Confidence: 0.5
|
||||
- When he pastes a runtime error/log (e.g., a tRPC/D1 `Failed query: select ... from "key_val_store"` 500), he asks for an explanation first — "what does this error mean. Why am I seeing it" — expecting the agent to investigate and explain the root cause (local D1 state, migrations/config) before changing any code, not to jump straight to a fix. Confidence: 0.5
|
||||
e changes. Confidence: 0.95
|
||||
er-ui/app/(drawer)/(tabs)/home/index.tsx, I want similar here") and expects the agent to mirror that pattern exactly, including details like item counts and container styling. Confidence: 0.9
|
||||
als) rather than introducing new brand palettes; approval of a redesign's layout/composition does not imply approval of color or theme changes. Confidence: 0.95
|
||||
|
|
|
|||
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -133,10 +133,3 @@ dist
|
|||
|
||||
|
||||
type-clusters/*
|
||||
|
||||
# ---> Maestro (root E2E suite)
|
||||
tests/e2e/.env
|
||||
|
||||
apps/user-ui/android/
|
||||
apps/admin-ui/android/
|
||||
.maestro-output/*
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
## Important instructions
|
||||
- Don't run any drizzle migrations. User will handle it.
|
||||
- don't try to run any test unless user explicitly asks for
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@ const MenuItemComponent: React.FC<MenuItemComponentProps> = ({ item, router }) =
|
|||
|
||||
return (
|
||||
<Pressable
|
||||
testID={item.testID}
|
||||
accessibilityLabel={item.testID}
|
||||
onPress={() => item.onPress ? item.onPress() : router.push(item.route as any)}
|
||||
style={({ pressed }) => [
|
||||
tw`flex-row items-center p-4 bg-white border border-gray-100 rounded-xl mb-3 shadow-sm`,
|
||||
|
|
@ -110,7 +108,6 @@ export default function Dashboard() {
|
|||
description: 'Create a new product listing',
|
||||
route: '/(drawer)/dashboard/products/add',
|
||||
category: 'quick',
|
||||
testID: 'add-product-menu-item',
|
||||
iconColor: theme.colors.brand500,
|
||||
iconBg: theme.colors.brand50,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,19 +1,10 @@
|
|||
import React from 'react'
|
||||
import { Alert, View } from 'react-native'
|
||||
import { ImageUploaderNeoPayload, tw } from 'common-ui'
|
||||
import { Alert } from 'react-native'
|
||||
import { AppContainer, ImageUploaderNeoPayload } from 'common-ui'
|
||||
import ProductForm from '@/src/components/ProductForm'
|
||||
import { trpc } from '@/src/trpc-client'
|
||||
import { useUploadToObjectStorage } from '@/hooks/useUploadToObjectStore'
|
||||
|
||||
// SKUs store bucket-relative object keys, not URLs. Drop the query string and
|
||||
// keep the last two path segments:
|
||||
// https://<acct>.r2.cloudflarestorage.com/meatfarmer-dev/product-images/1.jpg?X-Amz-...
|
||||
// -> product-images/1.jpg
|
||||
const toImageKey = (url: string): string => {
|
||||
const parts = url.split('?')[0].split('/').filter(Boolean)
|
||||
return parts.slice(-2).join('/')
|
||||
}
|
||||
|
||||
export default function AddProduct() {
|
||||
const createProduct = trpc.admin.product.createProduct.useMutation()
|
||||
const { refetch: refetchProducts } = trpc.admin.product.getProducts.useQuery(undefined, {
|
||||
|
|
@ -72,8 +63,7 @@ export default function AddProduct() {
|
|||
let urlCursor = 0
|
||||
const skus = values.variants.map((variant: any, vIndex: number) => {
|
||||
const count = imageCounts[vIndex]
|
||||
// Send keys, not the presigned URLs.
|
||||
const variantUrls = allUploadUrls.slice(urlCursor, urlCursor + count).map(toImageKey)
|
||||
const variantUrls = allUploadUrls.slice(urlCursor, urlCursor + count)
|
||||
urlCursor += count
|
||||
|
||||
return {
|
||||
|
|
@ -139,13 +129,13 @@ export default function AddProduct() {
|
|||
}
|
||||
|
||||
return (
|
||||
<View style={tw`flex-1 bg-white`}>
|
||||
<AppContainer>
|
||||
<ProductForm
|
||||
mode="create"
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
isLoading={createProduct.isPending || isUploading}
|
||||
/>
|
||||
</View>
|
||||
</AppContainer>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,15 +6,6 @@ import ProductForm, { ProductFormRef } from '@/src/components/ProductForm';
|
|||
import { trpc } from '@/src/trpc-client';
|
||||
import { useUploadToObjectStorage } from '@/hooks/useUploadToObjectStore';
|
||||
|
||||
// SKUs store bucket-relative object keys, not URLs. Drop the query string and
|
||||
// keep the last two path segments:
|
||||
// https://<acct>.r2.cloudflarestorage.com/meatfarmer-dev/product-images/1.jpg?X-Amz-...
|
||||
// -> product-images/1.jpg
|
||||
const toImageKey = (url: string): string => {
|
||||
const parts = url.split('?')[0].split('/').filter(Boolean)
|
||||
return parts.slice(-2).join('/')
|
||||
}
|
||||
|
||||
export default function EditProduct() {
|
||||
const { id } = useLocalSearchParams();
|
||||
const productId = Number(id);
|
||||
|
|
@ -149,10 +140,9 @@ export default function EditProduct() {
|
|||
// Existing images (mimeType === null) stay as-is
|
||||
const existingUrls = variantImages[vIndex]
|
||||
?.filter((img) => img.mimeType === null)
|
||||
.map((img) => toImageKey(img.url)) || []
|
||||
.map((img) => img.url) || []
|
||||
|
||||
// Send keys, not URLs — the SKU stores the bucket-relative object key.
|
||||
const allUrls = [...existingUrls, ...newUrls.map(toImageKey)]
|
||||
const allUrls = [...existingUrls, ...newUrls]
|
||||
|
||||
return {
|
||||
id: variant.id,
|
||||
|
|
@ -219,7 +209,7 @@ export default function EditProduct() {
|
|||
}
|
||||
|
||||
return (
|
||||
<View style={tw`flex-1 bg-white`}>
|
||||
<AppContainer>
|
||||
<ProductForm
|
||||
ref={productFormRef}
|
||||
mode="edit"
|
||||
|
|
@ -229,6 +219,6 @@ export default function EditProduct() {
|
|||
existingVariantImages={existingVariantImages}
|
||||
existingVariantImageKeys={existingVariantImageKeys}
|
||||
/>
|
||||
</View>
|
||||
</AppContainer>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import React, { useState, useMemo, useCallback } from 'react';
|
||||
import { View, TouchableOpacity } from 'react-native';
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { View, TouchableOpacity, RefreshControl } from 'react-native';
|
||||
import { Image } from 'expo-image';
|
||||
import { useRouter } from 'expo-router';
|
||||
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
||||
import { MyText, tw, MyButton, useManualRefresh, SearchBar, useMarkDataFetchers, MyFlatList } from 'common-ui';
|
||||
import { AppContainer, MyText, tw, MyButton, useManualRefresh, SearchBar, useMarkDataFetchers, MyFlatList } from 'common-ui';
|
||||
|
||||
import { trpc } from '@/src/trpc-client';
|
||||
import { SuccessToast, ErrorToast } from '@/services/toaster';
|
||||
|
|
@ -13,130 +13,15 @@ type FilterType = 'all' | 'in-stock' | 'out-of-stock';
|
|||
|
||||
type SerializedAdminSku = Omit<AdminSku, 'createdAt'> & { createdAt: string | Date }
|
||||
|
||||
function getDefaultSku(product: { skus?: SerializedAdminSku[] }): SerializedAdminSku | null {
|
||||
function getDefaultSku(product: { skus: SerializedAdminSku[] }): SerializedAdminSku | null {
|
||||
return product.skus?.[0] ?? null
|
||||
}
|
||||
|
||||
function FilterButton({
|
||||
filter,
|
||||
label,
|
||||
count,
|
||||
activeFilter,
|
||||
onSelect,
|
||||
}: {
|
||||
filter: FilterType
|
||||
label: string
|
||||
count: number
|
||||
activeFilter: FilterType
|
||||
onSelect: (filter: FilterType) => void
|
||||
}) {
|
||||
const isActive = activeFilter === filter
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={() => onSelect(filter)}
|
||||
style={tw`px-4 py-2 rounded-lg ${isActive ? 'bg-blue-500' : 'bg-gray-200'}`}
|
||||
>
|
||||
<MyText style={tw`${isActive ? 'text-white' : 'text-gray-700'} font-semibold`}>
|
||||
{label} ({count})
|
||||
</MyText>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
|
||||
type ProductRowProps = {
|
||||
product: any
|
||||
isToggling: boolean
|
||||
onView: (productId: number) => void
|
||||
onEdit: (productId: number) => void
|
||||
onToggle: (product: { id: number }) => void
|
||||
}
|
||||
|
||||
const ProductRow = React.memo(function ProductRow({ product, isToggling, onView, onEdit, onToggle }: ProductRowProps) {
|
||||
const defaultSku = getDefaultSku(product)
|
||||
const skuImages = defaultSku?.images ?? null
|
||||
const isOut = defaultSku?.isOutOfStock ?? false
|
||||
|
||||
return (
|
||||
<View style={tw`bg-white rounded-2xl shadow-lg mb-4 overflow-hidden`}>
|
||||
{/* Product Image */}
|
||||
{skuImages && skuImages.length > 0 ? (
|
||||
<Image
|
||||
source={{ uri: skuImages[0] }}
|
||||
style={tw`w-full h-48`}
|
||||
contentFit="cover"
|
||||
cachePolicy="memory-disk"
|
||||
recyclingKey={String(product.id)}
|
||||
/>
|
||||
) : (
|
||||
<View style={tw`w-full h-48 bg-gray-200 justify-center items-center`}>
|
||||
<MaterialIcons name="image" size={48} color="#9CA3AF" />
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Product Info */}
|
||||
<View style={tw`p-4`}>
|
||||
<View style={tw`flex-row justify-between items-start mb-2`}>
|
||||
<MyText style={tw`text-lg font-bold text-gray-800 flex-1 mr-2`} numberOfLines={2}>
|
||||
{product.name}
|
||||
</MyText>
|
||||
<View style={tw`flex-row items-center`}>
|
||||
<View style={tw`w-3 h-3 rounded-full mr-1 ${isOut ? 'bg-red-500' : 'bg-green-500'}`} />
|
||||
<MyText style={tw`text-sm ${isOut ? 'text-red-500' : 'text-green-500'} font-semibold`}>
|
||||
{isOut ? 'Out' : 'In'}
|
||||
</MyText>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{product.shortDescription && (
|
||||
<MyText style={tw`text-gray-600 mb-2`} numberOfLines={2}>
|
||||
{product.shortDescription}
|
||||
</MyText>
|
||||
)}
|
||||
|
||||
<View style={tw`flex-row justify-between items-center mb-3`}>
|
||||
<MyText style={tw`text-sm text-gray-500 font-medium`}>
|
||||
{product.skus?.length ?? 0} Variants
|
||||
</MyText>
|
||||
</View>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<View style={tw`flex-row gap-2`}>
|
||||
<TouchableOpacity
|
||||
onPress={() => onView(product.id)}
|
||||
style={tw`flex-1 bg-gray-500 p-3 rounded-lg flex-row items-center justify-center`}
|
||||
>
|
||||
<MaterialIcons name="visibility" size={16} color="white" />
|
||||
<MyText style={tw`text-white font-semibold ml-1`}>View</MyText>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={() => onEdit(product.id)}
|
||||
style={tw`flex-1 bg-blue-500 p-3 rounded-lg flex-row items-center justify-center`}
|
||||
>
|
||||
<MaterialIcons name="edit" size={16} color="white" />
|
||||
<MyText style={tw`text-white font-semibold ml-1`}>Edit</MyText>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={() => onToggle(product)}
|
||||
disabled={isToggling}
|
||||
style={tw`flex-1 ${isOut ? 'bg-green-500' : 'bg-orange-500'} p-3 rounded-lg flex-row items-center justify-center ${isToggling ? 'opacity-50' : ''}`}
|
||||
>
|
||||
<MaterialIcons name={isOut ? 'check-circle' : 'block'} size={16} color="white" />
|
||||
<MyText style={tw`text-white font-semibold ml-1`}>
|
||||
{isOut ? 'Stock' : 'Out'}
|
||||
</MyText>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
})
|
||||
|
||||
export default function Products() {
|
||||
const router = useRouter();
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
const [activeFilter, setActiveFilter] = useState<FilterType>('all');
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
|
||||
const { data: productsData, isLoading, error, refetch } = trpc.admin.product.getProducts.useQuery();
|
||||
|
||||
|
|
@ -158,17 +43,18 @@ export default function Products() {
|
|||
|
||||
const products = productsData?.products || [];
|
||||
|
||||
const handleRefresh = useCallback(async () => {
|
||||
const handleRefresh = async () => {
|
||||
setRefreshing(true);
|
||||
await refetch();
|
||||
}, [refetch]);
|
||||
setRefreshing(false);
|
||||
};
|
||||
|
||||
const filteredProducts = useMemo(() => {
|
||||
const term = searchTerm.toLowerCase();
|
||||
return products.filter(product => {
|
||||
const defaultSku = getDefaultSku(product)
|
||||
|
||||
const matchesSearch = product.name.toLowerCase().includes(term) ||
|
||||
(product.shortDescription?.toLowerCase().includes(term));
|
||||
const matchesSearch = product.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
(product.shortDescription?.toLowerCase().includes(searchTerm.toLowerCase()));
|
||||
|
||||
const matchesFilter = activeFilter === 'all' ||
|
||||
(activeFilter === 'in-stock' && !defaultSku?.isOutOfStock) ||
|
||||
|
|
@ -178,47 +64,64 @@ export default function Products() {
|
|||
});
|
||||
}, [products, searchTerm, activeFilter]);
|
||||
|
||||
const inStockCount = useMemo(
|
||||
() => products.filter(p => { const sku = getDefaultSku(p); return sku && !sku.isOutOfStock }).length,
|
||||
[products]
|
||||
);
|
||||
const outOfStockCount = useMemo(
|
||||
() => products.filter(p => getDefaultSku(p)?.isOutOfStock).length,
|
||||
[products]
|
||||
);
|
||||
|
||||
const handleEdit = useCallback((productId: number) => {
|
||||
const handleEdit = (productId: number) => {
|
||||
router.push(`/(drawer)/dashboard/products/edit?id=${productId}` as any);
|
||||
}, [router]);
|
||||
};
|
||||
|
||||
const handleViewDetails = useCallback((productId: number) => {
|
||||
const handleViewDetails = (productId: number) => {
|
||||
router.push(`/(drawer)/dashboard/products/detail/${productId}` as any);
|
||||
}, [router]);
|
||||
};
|
||||
|
||||
const handleToggleStock = useCallback((product: { id: number }) => {
|
||||
const handleToggleStock = (product: { id: number }) => {
|
||||
toggleOutOfStock.mutate({ id: product.id });
|
||||
}, [toggleOutOfStock]);
|
||||
};
|
||||
|
||||
const handleSelectFilter = useCallback((filter: FilterType) => setActiveFilter(filter), []);
|
||||
const FilterButton = ({ filter, label, count }: { filter: FilterType; label: string; count: number }) => (
|
||||
<TouchableOpacity
|
||||
onPress={() => setActiveFilter(filter)}
|
||||
style={tw`px-4 py-2 rounded-lg ${activeFilter === filter ? 'bg-blue-500' : 'bg-gray-200'}`}
|
||||
>
|
||||
<MyText style={tw`${activeFilter === filter ? 'text-white' : 'text-gray-700'} font-semibold`}>
|
||||
{label} ({count})
|
||||
</MyText>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
const keyExtractor = useCallback((item: { id: number }) => item.id.toString(), []);
|
||||
if (isLoading) {
|
||||
return (
|
||||
<AppContainer>
|
||||
<View style={tw`flex-1 justify-center items-center`}>
|
||||
<MyText style={tw`text-gray-600`}>Loading products...</MyText>
|
||||
</View>
|
||||
</AppContainer>
|
||||
);
|
||||
}
|
||||
|
||||
const renderItem = useCallback(({ item: product }: { item: any }) => (
|
||||
<ProductRow
|
||||
product={product}
|
||||
isToggling={toggleOutOfStock.isPending && toggleOutOfStock.variables?.id === product.id}
|
||||
onView={handleViewDetails}
|
||||
onEdit={handleEdit}
|
||||
onToggle={handleToggleStock}
|
||||
/>
|
||||
), [toggleOutOfStock.isPending, toggleOutOfStock.variables?.id, handleViewDetails, handleEdit, handleToggleStock]);
|
||||
if (error) {
|
||||
return (
|
||||
<AppContainer>
|
||||
<View style={tw`flex-1 justify-center items-center`}>
|
||||
<MyText style={tw`text-red-600`}>Error loading products</MyText>
|
||||
<TouchableOpacity
|
||||
onPress={() => refetch()}
|
||||
style={tw`mt-4 bg-blue-500 px-4 py-2 rounded-lg`}
|
||||
>
|
||||
<MyText style={tw`text-white font-semibold`}>Retry</MyText>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</AppContainer>
|
||||
);
|
||||
}
|
||||
|
||||
const listHeader = useMemo(() => (
|
||||
const inStockCount = products.filter(p => getDefaultSku(p) && !getDefaultSku(p)!.isOutOfStock).length;
|
||||
const outOfStockCount = products.filter(p => getDefaultSku(p)?.isOutOfStock).length;
|
||||
|
||||
const listHeader = (
|
||||
<>
|
||||
{/* Header */}
|
||||
<View style={tw`flex-row justify-between items-center mb-6`}>
|
||||
<MyText style={tw`text-2xl font-bold text-gray-800`}>Products</MyText>
|
||||
<MyButton testID="add-product-button" onPress={() => router.push('/(drawer)/dashboard/products/add' as any)}>
|
||||
<MyButton onPress={() => router.push('/(drawer)/dashboard/products/add' as any)}>
|
||||
Add Product
|
||||
</MyButton>
|
||||
</View>
|
||||
|
|
@ -235,72 +138,130 @@ export default function Products() {
|
|||
|
||||
{/* Filter Tabs */}
|
||||
<View style={tw`flex-row gap-2 mb-6`}>
|
||||
<FilterButton filter="all" label="All" count={products.length} activeFilter={activeFilter} onSelect={handleSelectFilter} />
|
||||
<FilterButton filter="in-stock" label="In Stock" count={inStockCount} activeFilter={activeFilter} onSelect={handleSelectFilter} />
|
||||
<FilterButton filter="out-of-stock" label="Out of Stock" count={outOfStockCount} activeFilter={activeFilter} onSelect={handleSelectFilter} />
|
||||
<FilterButton filter="all" label="All" count={products.length} />
|
||||
<FilterButton filter="in-stock" label="In Stock" count={inStockCount} />
|
||||
<FilterButton filter="out-of-stock" label="Out of Stock" count={outOfStockCount} />
|
||||
</View>
|
||||
</>
|
||||
), [products.length, inStockCount, outOfStockCount, searchTerm, activeFilter, handleSelectFilter, router]);
|
||||
);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<View style={tw`flex-1 bg-white justify-center items-center`}>
|
||||
<MyText style={tw`text-gray-600`}>Loading products...</MyText>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
const renderItem = ({ item: product }: { item: any }) => {
|
||||
const defaultSku = getDefaultSku(product)
|
||||
const skuImages = defaultSku?.images ?? null
|
||||
const isOut = defaultSku?.isOutOfStock ?? false
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<View style={tw`flex-1 bg-white justify-center items-center`}>
|
||||
<MyText style={tw`text-red-600`}>Error loading products</MyText>
|
||||
<TouchableOpacity
|
||||
onPress={() => refetch()}
|
||||
style={tw`mt-4 bg-blue-500 px-4 py-2 rounded-lg`}
|
||||
>
|
||||
<MyText style={tw`text-white font-semibold`}>Retry</MyText>
|
||||
</TouchableOpacity>
|
||||
<View key={product.id} style={tw`bg-white rounded-2xl shadow-lg mb-4 overflow-hidden`}>
|
||||
{/* Product Image */}
|
||||
{skuImages && skuImages.length > 0 ? (
|
||||
<Image
|
||||
source={{ uri: skuImages[0] }}
|
||||
style={tw`w-full h-48`}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
) : (
|
||||
<View style={tw`w-full h-48 bg-gray-200 justify-center items-center`}>
|
||||
<MaterialIcons name="image" size={48} color="#9CA3AF" />
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Product Info */}
|
||||
<View style={tw`p-4`}>
|
||||
<View style={tw`flex-row justify-between items-start mb-2`}>
|
||||
<MyText style={tw`text-lg font-bold text-gray-800 flex-1 mr-2`} numberOfLines={2}>
|
||||
{product.name}
|
||||
</MyText>
|
||||
<View style={tw`flex-row items-center`}>
|
||||
<View style={tw`w-3 h-3 rounded-full mr-1 ${isOut ? 'bg-red-500' : 'bg-green-500'}`} />
|
||||
<MyText style={tw`text-sm ${isOut ? 'text-red-500' : 'text-green-500'} font-semibold`}>
|
||||
{isOut ? 'Out' : 'In'}
|
||||
</MyText>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{product.shortDescription && (
|
||||
<MyText style={tw`text-gray-600 mb-2`} numberOfLines={2}>
|
||||
{product.shortDescription}
|
||||
</MyText>
|
||||
)}
|
||||
|
||||
<View style={tw`flex-row justify-between items-center mb-3`}>
|
||||
<MyText style={tw`text-sm text-gray-500 font-medium`}>
|
||||
{product.skus?.length ?? 0} Variants
|
||||
</MyText>
|
||||
</View>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<View style={tw`flex-row gap-2`}>
|
||||
<TouchableOpacity
|
||||
onPress={() => handleViewDetails(product.id)}
|
||||
style={tw`flex-1 bg-gray-500 p-3 rounded-lg flex-row items-center justify-center`}
|
||||
>
|
||||
<MaterialIcons name="visibility" size={16} color="white" />
|
||||
<MyText style={tw`text-white font-semibold ml-1`}>View</MyText>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={() => handleEdit(product.id)}
|
||||
style={tw`flex-1 bg-blue-500 p-3 rounded-lg flex-row items-center justify-center`}
|
||||
>
|
||||
<MaterialIcons name="edit" size={16} color="white" />
|
||||
<MyText style={tw`text-white font-semibold ml-1`}>Edit</MyText>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
onPress={() => handleToggleStock(product)}
|
||||
disabled={toggleOutOfStock.isPending && toggleOutOfStock.variables?.id === product.id}
|
||||
style={tw`flex-1 ${isOut ? 'bg-green-500' : 'bg-orange-500'} p-3 rounded-lg flex-row items-center justify-center ${toggleOutOfStock.isPending && toggleOutOfStock.variables?.id === product.id ? 'opacity-50' : ''}`}
|
||||
>
|
||||
<MaterialIcons name={isOut ? 'check-circle' : 'block'} size={16} color="white" />
|
||||
<MyText style={tw`text-white font-semibold ml-1`}>
|
||||
{isOut ? 'Stock' : 'Out'}
|
||||
</MyText>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={tw`flex-1 bg-white`}>
|
||||
<MyFlatList
|
||||
data={filteredProducts}
|
||||
renderItem={renderItem}
|
||||
keyExtractor={keyExtractor}
|
||||
ListHeaderComponent={listHeader}
|
||||
ListEmptyComponent={
|
||||
<View style={tw`flex-1 justify-center items-center py-10`}>
|
||||
<MaterialIcons name="inventory" size={64} color="#D1D5DB" />
|
||||
<MyText style={tw`text-gray-500 text-center mt-4 text-lg`}>
|
||||
{searchTerm || activeFilter !== 'all' ? 'No products match your filters' : 'No products found'}
|
||||
</MyText>
|
||||
<MyText style={tw`text-gray-400 text-center mt-2`}>
|
||||
{searchTerm || activeFilter !== 'all' ? 'Try adjusting your search or filters' : 'Start by adding your first product'}
|
||||
</MyText>
|
||||
{(searchTerm || activeFilter !== 'all') && (
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
setSearchTerm('');
|
||||
setActiveFilter('all');
|
||||
}}
|
||||
style={tw`mt-4 bg-blue-500 px-4 py-2 rounded-lg`}
|
||||
>
|
||||
<MyText style={tw`text-white font-semibold`}>Clear Filters</MyText>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
}
|
||||
contentContainerStyle={tw`p-4`}
|
||||
showsVerticalScrollIndicator={false}
|
||||
onRefresh={handleRefresh}
|
||||
initialNumToRender={6}
|
||||
maxToRenderPerBatch={8}
|
||||
windowSize={5}
|
||||
removeClippedSubviews
|
||||
/>
|
||||
</View>
|
||||
<AppContainer>
|
||||
<View style={tw`flex-1`}>
|
||||
<MyFlatList
|
||||
data={filteredProducts}
|
||||
renderItem={renderItem}
|
||||
keyExtractor={(item) => item.id.toString()}
|
||||
ListHeaderComponent={listHeader}
|
||||
ListEmptyComponent={
|
||||
<View style={tw`flex-1 justify-center items-center py-10`}>
|
||||
<MaterialIcons name="inventory" size={64} color="#D1D5DB" />
|
||||
<MyText style={tw`text-gray-500 text-center mt-4 text-lg`}>
|
||||
{searchTerm || activeFilter !== 'all' ? 'No products match your filters' : 'No products found'}
|
||||
</MyText>
|
||||
<MyText style={tw`text-gray-400 text-center mt-2`}>
|
||||
{searchTerm || activeFilter !== 'all' ? 'Try adjusting your search or filters' : 'Start by adding your first product'}
|
||||
</MyText>
|
||||
{(searchTerm || activeFilter !== 'all') && (
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
setSearchTerm('');
|
||||
setActiveFilter('all');
|
||||
}}
|
||||
style={tw`mt-4 bg-blue-500 px-4 py-2 rounded-lg`}
|
||||
>
|
||||
<MyText style={tw`text-white font-semibold`}>Clear Filters</MyText>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
}
|
||||
contentContainerStyle={tw`pb-4`}
|
||||
showsVerticalScrollIndicator={false}
|
||||
refreshControl={
|
||||
<RefreshControl refreshing={refreshing} onRefresh={handleRefresh} />
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
</AppContainer>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState } from 'react';
|
||||
import { MaterialCommunityIcons, Entypo } from '@expo/vector-icons';
|
||||
import { View, TouchableOpacity, FlatList, Alert, ActivityIndicator } from 'react-native';
|
||||
import { MyText, tw, MyFlatList , BottomDialog, MyTouchableOpacity, Checkbox } from 'common-ui';
|
||||
import { AppContainer, MyText, tw, MyFlatList , BottomDialog, MyTouchableOpacity, Checkbox } from 'common-ui';
|
||||
import { trpc } from '@/src/trpc-client';
|
||||
import { useRouter } from 'expo-router';
|
||||
import dayjs from 'dayjs';
|
||||
|
|
|
|||
|
|
@ -198,7 +198,6 @@ export default function SlotDetails() {
|
|||
|
||||
{/* FAB for Edit Slot */}
|
||||
<MyTouchableOpacity
|
||||
testID="edit-slot-fab"
|
||||
onPress={() => router.push(`/(drawer)/dashboard/slots/edit/${slot.id}` as any)}
|
||||
activeOpacity={0.95}
|
||||
style={{ position: 'absolute', bottom: 32, right: 24, zIndex: 100 }}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,11 @@
|
|||
import { QueryClientProvider } from "@tanstack/react-query";
|
||||
import queryClient from "../utils/queryClient";
|
||||
import { Stack } from "expo-router";
|
||||
import { LogBox } from "react-native";
|
||||
import { StaffAuthProvider } from "@/components/context/staff-auth-context";
|
||||
import { trpc, trpcClient } from "@/src/trpc-client";
|
||||
import { SafeAreaView } from "react-native-safe-area-context";
|
||||
import { RefreshProvider } from '../../../packages/ui/src/lib/refresh-context';
|
||||
|
||||
// Silence dev warnings/errors in LogBox. The "Open debugger to view warnings"
|
||||
// toast overlays the bottom of the UI and intercepts taps (e.g. the Add Slot
|
||||
// FAB), which breaks E2E flows.
|
||||
if (__DEV__) {
|
||||
LogBox.ignoreAllLogs(true);
|
||||
}
|
||||
|
||||
export default function Layout() {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ interface ProductsSelectorProps {
|
|||
selectedGroupIds?: number[];
|
||||
onGroupChange?: (groupIds: number[]) => void;
|
||||
showGroups?: boolean;
|
||||
testID?: string;
|
||||
}
|
||||
|
||||
export default function ProductsSelector({
|
||||
|
|
@ -45,7 +44,6 @@ export default function ProductsSelector({
|
|||
showGroups = true,
|
||||
selectedGroupIds = [],
|
||||
onGroupChange,
|
||||
testID,
|
||||
}: ProductsSelectorProps) {
|
||||
const { data: skusData } = trpc.common.product.getAllSkusSummary.useQuery();
|
||||
const allSkus: SkuSummary[] = skusData?.skus || [];
|
||||
|
|
@ -149,7 +147,6 @@ export default function ProductsSelector({
|
|||
)}
|
||||
|
||||
<BottomDropdown
|
||||
testID={testID}
|
||||
label={label}
|
||||
options={productOptions}
|
||||
value={multiple
|
||||
|
|
|
|||
|
|
@ -160,7 +160,6 @@ export default function SlotForm({
|
|||
selectedGroupIds={values.selectedGroupIds}
|
||||
onGroupChange={(newGroupIds) => setFieldValue('selectedGroupIds', newGroupIds)}
|
||||
label="Select Products"
|
||||
testID="slot-products-selector"
|
||||
placeholder="Select products for this slot"
|
||||
/>
|
||||
</View>
|
||||
|
|
@ -194,7 +193,6 @@ export default function SlotForm({
|
|||
selectedGroupIds={snippet.groupIds || []}
|
||||
onGroupChange={(newGroupIds) => setFieldValue(`vendorSnippetList.${index}.groupIds`, newGroupIds)}
|
||||
label="Select Products"
|
||||
testID="snippet-products-selector"
|
||||
placeholder="Select products for snippet"
|
||||
isDisabled={(sku) => !values.selectedSkuIds.includes(sku.id)}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -43,11 +43,9 @@ export function useUploadToObjectStorage() {
|
|||
headers: { 'Content-Type': mimeType },
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const body = await response.text(); // <Error><Code>…</Code></Error>
|
||||
console.error('upload failed', response.status, body);
|
||||
throw new Error(`Upload ${index + 1} failed with status ${response.status}`);
|
||||
}
|
||||
if (!response.ok) {
|
||||
throw new Error(`Upload ${index + 1} failed with status ${response.status}`);
|
||||
}
|
||||
|
||||
// Update progress
|
||||
setProgress(prev => prev ? { ...prev, completed: prev.completed + 1 } : null);
|
||||
|
|
|
|||
|
|
@ -253,9 +253,8 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
>
|
||||
{({ handleChange, handleSubmit, values, setFieldValue, validateForm }) => {
|
||||
return (
|
||||
<ScrollView style={tw`flex-1`} contentContainerStyle={tw`px-4 pt-4 pb-10`} keyboardShouldPersistTaps="handled">
|
||||
<ScrollView style={tw`flex-1`} contentContainerStyle={tw`pb-10`}>
|
||||
<MyTextInput
|
||||
testID="product-name-input"
|
||||
topLabel="Product Name"
|
||||
placeholder="Enter product name"
|
||||
value={values.name}
|
||||
|
|
@ -263,7 +262,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
<MyTextInput
|
||||
testID="product-short-description-input"
|
||||
topLabel="Short Description"
|
||||
placeholder="Enter short description"
|
||||
multiline
|
||||
|
|
@ -273,7 +271,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
<MyTextInput
|
||||
testID="product-long-description-input"
|
||||
topLabel="Long Description"
|
||||
placeholder="Enter detailed description"
|
||||
multiline
|
||||
|
|
@ -283,7 +280,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
<BottomDropdown
|
||||
testID="product-store-dropdown"
|
||||
topLabel="Store"
|
||||
label="Store"
|
||||
value={values.storeId}
|
||||
|
|
@ -294,7 +290,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
/>
|
||||
|
||||
<BottomDropdown
|
||||
testID="product-type-dropdown"
|
||||
topLabel="Product Type"
|
||||
label="Product Type"
|
||||
value={values.productType}
|
||||
|
|
@ -313,7 +308,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
<View style={tw`flex-row justify-between items-center mb-3`}>
|
||||
<MyText style={tw`text-lg font-bold text-gray-800`}>Variants</MyText>
|
||||
<TouchableOpacity
|
||||
testID="add-variant-button"
|
||||
onPress={() => {
|
||||
push(defaultVariant())
|
||||
setVariantImages((prev) => [...prev, []])
|
||||
|
|
@ -341,7 +335,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
</View>
|
||||
{(values.variants.length > 1 || isExistingSku) && (
|
||||
<TouchableOpacity
|
||||
testID={`variant-${vIndex}-remove`}
|
||||
onPress={() => {
|
||||
if (isExistingSku) {
|
||||
// Mark existing SKU as deleted (sent to backend on save).
|
||||
|
|
@ -362,7 +355,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
</View>
|
||||
|
||||
<MyTextInput
|
||||
testID={`variant-${vIndex}-sku-name`}
|
||||
topLabel="SKU Name (optional)"
|
||||
placeholder="Overrides the auto-generated name"
|
||||
value={variant.name ?? ''}
|
||||
|
|
@ -393,7 +385,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
<View key={aIndex} style={tw`flex-row items-center mb-2 gap-2`}>
|
||||
<View style={tw`flex-1`}>
|
||||
<MyTextInput
|
||||
testID={`variant-${vIndex}-attr-${aIndex}-name`}
|
||||
placeholder="Name"
|
||||
value={attr.featureName ?? ''}
|
||||
onChangeText={(text) =>
|
||||
|
|
@ -408,7 +399,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
</View>
|
||||
<View style={tw`flex-1`}>
|
||||
<MyTextInput
|
||||
testID={`variant-${vIndex}-attr-${aIndex}-value`}
|
||||
placeholder={isQuantityFeature(attr) ? 'e.g. 0.5 kg' : 'Value'}
|
||||
value={attr.featureValue}
|
||||
onChangeText={handleChange(`variants.${vIndex}.features.${aIndex}.featureValue`)}
|
||||
|
|
@ -442,7 +432,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
<View style={tw`flex-row gap-2 mb-3`}>
|
||||
<View style={tw`flex-1`}>
|
||||
<MyTextInput
|
||||
testID={`variant-${vIndex}-market-price`}
|
||||
topLabel="Market Price"
|
||||
placeholder="MRP"
|
||||
keyboardType="numeric"
|
||||
|
|
@ -453,7 +442,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
<View style={tw`flex-1`}>
|
||||
<MyTextInput
|
||||
topLabel="Our Price"
|
||||
testID={`variant-${vIndex}-price`}
|
||||
placeholder="Selling price"
|
||||
keyboardType="numeric"
|
||||
value={variant.price?.toString() ?? ''}
|
||||
|
|
@ -464,7 +452,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
|
||||
<View style={tw`flex-row items-center mb-3`}>
|
||||
<Checkbox
|
||||
testID={`variant-${vIndex}-flash`}
|
||||
checked={variant.isFlashAvailable}
|
||||
onPress={() => {
|
||||
setFieldValue(`variants.${vIndex}.isFlashAvailable`, !variant.isFlashAvailable)
|
||||
|
|
@ -477,7 +464,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
|
||||
<View style={tw`flex-row items-center mb-3`}>
|
||||
<Checkbox
|
||||
testID={`variant-${vIndex}-offer`}
|
||||
checked={variant.isOffer}
|
||||
onPress={() => setFieldValue(`variants.${vIndex}.isOffer`, !variant.isOffer)}
|
||||
style={tw`mr-3`}
|
||||
|
|
@ -488,7 +474,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
{!(values.productType === 'combo' && (variant.comboItems?.length || 0) > 0) && (
|
||||
<View style={tw`flex-row items-center mb-3`}>
|
||||
<Checkbox
|
||||
testID={`variant-${vIndex}-combo-only`}
|
||||
checked={variant.isComboOnly}
|
||||
onPress={() => setFieldValue(`variants.${vIndex}.isComboOnly`, !variant.isComboOnly)}
|
||||
style={tw`mr-3`}
|
||||
|
|
@ -500,7 +485,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
{mode === 'edit' && (
|
||||
<View style={tw`flex-row items-center mb-3`}>
|
||||
<Checkbox
|
||||
testID={`variant-${vIndex}-suspend`}
|
||||
checked={variant.isSuspended}
|
||||
onPress={() => setFieldValue(`variants.${vIndex}.isSuspended`, !variant.isSuspended)}
|
||||
style={tw`mr-3`}
|
||||
|
|
@ -511,7 +495,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
|
||||
{variant.isFlashAvailable && (
|
||||
<MyTextInput
|
||||
testID={`variant-${vIndex}-flash-price`}
|
||||
topLabel="Flash Price"
|
||||
placeholder="Enter flash price"
|
||||
keyboardType="numeric"
|
||||
|
|
@ -522,7 +505,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
)}
|
||||
|
||||
<ImageUploaderNeo
|
||||
testID={`variant-${vIndex}-image-add`}
|
||||
images={variantImages[vIndex] || []}
|
||||
onImageAdd={(payloads) =>
|
||||
setVariantImages((prev) => {
|
||||
|
|
@ -601,7 +583,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
})}
|
||||
|
||||
<TouchableOpacity
|
||||
testID="add-variant-button-footer"
|
||||
onPress={() => {
|
||||
push(defaultVariant())
|
||||
setVariantImages((prev) => [...prev, []])
|
||||
|
|
@ -616,7 +597,6 @@ const ProductForm = forwardRef<ProductFormRef, ProductFormProps>(({
|
|||
</FieldArray>
|
||||
|
||||
<TouchableOpacity
|
||||
testID="create-product-button"
|
||||
onPress={async () => {
|
||||
const validationErrors = await validateForm()
|
||||
if (Object.keys(validationErrors).length > 0) {
|
||||
|
|
|
|||
|
|
@ -118,14 +118,10 @@ export async function generateSignedUrlFromS3Url(s3UrlRaw: string|null, expiresI
|
|||
|
||||
try {
|
||||
const client = getAwsClient()
|
||||
// X-Amz-Expires must be a QUERY param, not a header: with signQuery, aws4fetch
|
||||
// hoists header values into the query but still lists them in
|
||||
// X-Amz-SignedHeaders, and R2 then hashes the missing header as empty — which
|
||||
// makes the signature mismatch (S3 tolerates it, R2 does not).
|
||||
const url = new URL(buildObjectUrl(getS3BucketName(), s3Url))
|
||||
url.searchParams.set('X-Amz-Expires', String(expiresIn))
|
||||
const signedRequest = await client.sign(url.toString(), {
|
||||
const url = buildObjectUrl(getS3BucketName(), s3Url)
|
||||
const signedRequest = await client.sign(url, {
|
||||
method: 'GET',
|
||||
headers: { 'X-Amz-Expires': String(expiresIn) },
|
||||
aws: { signQuery: true },
|
||||
})
|
||||
return signedRequest.url
|
||||
|
|
@ -174,13 +170,13 @@ export async function generateUploadUrl(key: string, mimeType: string, expiresIn
|
|||
await createUploadUrlStatus(key)
|
||||
|
||||
const client = getAwsClient()
|
||||
// Same as the GET path above: keep X-Amz-Expires in the query, and do not
|
||||
// sign Content-Type — leaving it unsigned means the client may send any value
|
||||
// without breaking the signature.
|
||||
const url = new URL(buildObjectUrl(getS3BucketName(), key))
|
||||
url.searchParams.set('X-Amz-Expires', String(expiresIn))
|
||||
const signedRequest = await client.sign(url.toString(), {
|
||||
const url = buildObjectUrl(getS3BucketName(), key)
|
||||
const signedRequest = await client.sign(url, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': mimeType,
|
||||
'X-Amz-Expires': String(expiresIn),
|
||||
},
|
||||
aws: { signQuery: true },
|
||||
})
|
||||
|
||||
|
|
@ -197,22 +193,15 @@ export async function generateUploadUrl(key: string, mimeType: string, expiresIn
|
|||
// return decodeURIComponent(rawKey);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Normalise an image reference to the bucket-relative object key that SKUs store.
|
||||
*
|
||||
* Accepts either a full (presigned) URL or an already-extracted key, so callers
|
||||
* can send whichever they have. Drops the query string, then keeps the last two
|
||||
* path segments:
|
||||
*
|
||||
* https://<account>.r2.cloudflarestorage.com/meatfarmer-dev/product-images/1.jpg?X-Amz-...
|
||||
* -> product-images/1.jpg
|
||||
* product-images/1.jpg
|
||||
* -> product-images/1.jpg
|
||||
*/
|
||||
// New function (excludes bucket name)
|
||||
export function extractKeyFromPresignedUrl(url: string): string {
|
||||
const withoutQuery = url.split('?')[0]
|
||||
const parts = withoutQuery.split('/').filter(Boolean)
|
||||
return decodeURIComponent(parts.slice(-2).join('/'))
|
||||
const u = new URL(url)
|
||||
const rawKey = u.pathname.replace(/^\/+/, '') // remove leading slash
|
||||
const decodedKey = decodeURIComponent(rawKey)
|
||||
// Remove bucket prefix
|
||||
const parts = decodedKey.split('/')
|
||||
parts.shift() // Remove bucket name
|
||||
return parts.join('/')
|
||||
}
|
||||
|
||||
export async function claimUploadUrl(url: string): Promise<void> {
|
||||
|
|
|
|||
|
|
@ -260,6 +260,8 @@ export const productRouter = router({
|
|||
await deleteImageUtil({ keys: deletedImageKeys })
|
||||
}
|
||||
|
||||
const allUploadUrls: string[] = skus.flatMap((sku) => sku.images)
|
||||
|
||||
const skuInputs = skus.map((sku) => ({
|
||||
id: sku.id,
|
||||
name: sku.name ?? null,
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ routes = [
|
|||
|
||||
[[d1_databases]]
|
||||
binding = "DB"
|
||||
#database_name = "freshyo-backend-dev"
|
||||
#database_id = "b2528bdb-0ec0-478e-8765-b118918153c0"
|
||||
database_name = "freshyo-dev"
|
||||
database_id = "3cad440f-dc14-4baa-ab05-04eb08e206de"
|
||||
database_name = "freshyo-backend-dev"
|
||||
database_id = "b2528bdb-0ec0-478e-8765-b118918153c0"
|
||||
#database_name = "freshyo-dev"
|
||||
#database_id = "3cad440f-dc14-4baa-ab05-04eb08e206de"
|
||||
migrations_dir="../../packages/db_helper_sqlite/drizzle"
|
||||
migrations_pattern="migration.sql"
|
||||
[durable_objects]
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
# EAS CLI ignores .gitignore entirely once this file exists, so the repo's
|
||||
# .gitignore patterns are reproduced here (see AGENTS.md / docs.expo.dev
|
||||
# build-reference/easignore). Keep this in sync when .gitignore changes.
|
||||
|
||||
# --- from root .gitignore ---
|
||||
node_modules/
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
coverage
|
||||
*.lcov
|
||||
.nyc_output
|
||||
bower_components
|
||||
build/Release
|
||||
jspm_packages/
|
||||
web_modules/
|
||||
*.tsbuildinfo
|
||||
.npm
|
||||
.eslintcache
|
||||
.stylelintcache
|
||||
.node_repl_history
|
||||
*.tgz
|
||||
.yarn-integrity
|
||||
.cache
|
||||
.parcel-cache
|
||||
.next
|
||||
out
|
||||
.nuxt
|
||||
dist
|
||||
.docusaurus
|
||||
.serverless/
|
||||
.fusebox/
|
||||
.dynamodb/
|
||||
.tern-port
|
||||
.vscode-test
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
type-clusters/*
|
||||
.maestro-output/*
|
||||
|
||||
# --- from apps/user-ui/.gitignore ---
|
||||
expo-env.d.ts
|
||||
.expo/
|
||||
|
||||
# --- EAS Build does not need these ---
|
||||
# Native projects are generated by Prebuild (matches git-ignored android/).
|
||||
android/
|
||||
ios/
|
||||
.turbo/
|
||||
|
||||
# Tests, fixtures and mocks are never part of a build.
|
||||
tests/
|
||||
|
||||
# Do not ship local secrets/config to the build servers.
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
|
@ -16,7 +16,6 @@ function Login() {
|
|||
const { loginWithToken } = useAuth();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [step, setStep] = useState<'mobile' | 'choice' | 'otp' | 'password'>('mobile');
|
||||
const [passwordBackTo, setPasswordBackTo] = useState<'mobile' | 'choice' | 'otp'>('choice');
|
||||
const [selectedMobile, setSelectedMobile] = useState('');
|
||||
const [canResend, setCanResend] = useState(false);
|
||||
const [resendCountdown, setResendCountdown] = useState(0);
|
||||
|
|
@ -136,9 +135,8 @@ function Login() {
|
|||
setError,
|
||||
clearErrors,
|
||||
setValue,
|
||||
watch,
|
||||
} = useForm<LoginFormInputs>({
|
||||
defaultValues: { mobile: "", otp: "", identifier: "", password: "" },
|
||||
defaultValues: { mobile: "", otp: "", password: "" },
|
||||
});
|
||||
|
||||
const validateMobile = (mobile: string): boolean => {
|
||||
|
|
@ -225,17 +223,7 @@ function Login() {
|
|||
otp: data.otp,
|
||||
});
|
||||
} else if (step === 'password') {
|
||||
// Login with username/email/mobile + password
|
||||
const identifier = (data.identifier || '').trim() || selectedMobile;
|
||||
|
||||
if (!identifier) {
|
||||
setError("identifier", {
|
||||
type: "manual",
|
||||
message: "Username is required",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Login with password
|
||||
if (!data.password || data.password.length < 6) {
|
||||
setError("password", {
|
||||
type: "manual",
|
||||
|
|
@ -246,7 +234,7 @@ function Login() {
|
|||
|
||||
try {
|
||||
const response = await loginMutation.mutateAsync({
|
||||
identifier,
|
||||
identifier: selectedMobile,
|
||||
password: data.password,
|
||||
});
|
||||
loginWithToken(response.data.token, response.data.user);
|
||||
|
|
@ -290,7 +278,6 @@ function Login() {
|
|||
render={({ field: { onChange, onBlur, value } }) => (
|
||||
<View style={tw`mb-5`}>
|
||||
<MyTextInput
|
||||
testID="user-login-mobile"
|
||||
topLabel="Mobile Number"
|
||||
placeholder="Enter your mobile number"
|
||||
value={value}
|
||||
|
|
@ -326,11 +313,7 @@ function Login() {
|
|||
<View style={tw`flex-row justify-between mb-6`}>
|
||||
<MyButton
|
||||
textContent="Use Password"
|
||||
onPress={() => {
|
||||
setPasswordBackTo('choice');
|
||||
setValue('identifier', selectedMobile);
|
||||
setStep('password');
|
||||
}}
|
||||
onPress={() => setStep('password')}
|
||||
fillColor="gray1"
|
||||
textColor="black1"
|
||||
style={tw`flex-1 mr-2 border border-gray-200`}
|
||||
|
|
@ -391,8 +374,6 @@ function Login() {
|
|||
|
||||
<MyTouchableOpacity
|
||||
onPress={() => {
|
||||
setPasswordBackTo('choice');
|
||||
setValue('identifier', selectedMobile);
|
||||
setStep('password');
|
||||
setValue('otp', '');
|
||||
setOtpCells(['', '', '', '']);
|
||||
|
|
@ -441,33 +422,6 @@ function Login() {
|
|||
|
||||
{step === 'password' && (
|
||||
<>
|
||||
<Controller
|
||||
control={control}
|
||||
name="identifier"
|
||||
render={({ field: { onChange, onBlur, value } }) => (
|
||||
<View style={tw`mb-4`}>
|
||||
<MyTextInput
|
||||
testID="user-login-identifier"
|
||||
topLabel="Username"
|
||||
placeholder="Enter your email or mobile"
|
||||
value={value}
|
||||
onChangeText={onChange}
|
||||
onBlur={onBlur}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
keyboardType="email-address"
|
||||
style={tw`bg-gray-50`}
|
||||
error={!!errors.identifier}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
/>
|
||||
{errors.identifier && (
|
||||
<MyText style={tw`text-red-500 text-sm mb-4 text-center`}>
|
||||
{errors.identifier.message}
|
||||
</MyText>
|
||||
)}
|
||||
|
||||
<Controller
|
||||
control={control}
|
||||
name="password"
|
||||
|
|
@ -475,7 +429,6 @@ function Login() {
|
|||
render={({ field: { onChange, onBlur, value } }) => (
|
||||
<View style={tw`mb-4`}>
|
||||
<MyTextInput
|
||||
testID="user-login-password"
|
||||
topLabel="Password"
|
||||
placeholder="Enter your password"
|
||||
value={value}
|
||||
|
|
@ -497,7 +450,7 @@ function Login() {
|
|||
<View style={tw`flex-row justify-center mb-6`}>
|
||||
<MyTouchableOpacity
|
||||
onPress={() => {
|
||||
setStep(passwordBackTo);
|
||||
setStep('choice');
|
||||
setValue('password', '');
|
||||
clearErrors();
|
||||
}}
|
||||
|
|
@ -531,7 +484,6 @@ function Login() {
|
|||
|
||||
<View style={tw`mt-4`}>
|
||||
<MyButton
|
||||
testID="user-login-submit"
|
||||
onPress={handleSubmit(onSubmit)}
|
||||
fillColor="brand600"
|
||||
textColor="white1"
|
||||
|
|
@ -550,23 +502,6 @@ function Login() {
|
|||
: (step === 'otp' ? "Verify & Login" : step === 'password' ? "Login" : "Continue")}
|
||||
</MyButton>
|
||||
</View>
|
||||
|
||||
{step === 'mobile' && (
|
||||
<MyTouchableOpacity
|
||||
testID="user-login-other-ways"
|
||||
onPress={() => {
|
||||
setPasswordBackTo('mobile');
|
||||
setValue('identifier', watch('mobile') || '');
|
||||
setStep('password');
|
||||
clearErrors();
|
||||
}}
|
||||
style={tw`mt-5`}
|
||||
>
|
||||
<MyText weight="semibold" style={tw`text-brand600 text-center`}>
|
||||
other ways to login
|
||||
</MyText>
|
||||
</MyTouchableOpacity>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -231,7 +231,6 @@ const TagTabStrip = memo(({
|
|||
return (
|
||||
<MyTouchableOpacity
|
||||
key={route.key}
|
||||
testID={`tag-tab-${route.key}`}
|
||||
onLayout={(e: any) => {
|
||||
positions.current[i] = e.nativeEvent.layout.x;
|
||||
}}
|
||||
|
|
@ -296,7 +295,7 @@ const TagScene = memo(({
|
|||
const hasMore = products.length > 6 && !expanded;
|
||||
|
||||
return (
|
||||
<View style={tw`mt-3`} testID={`tag-grid-${tagId}`}>
|
||||
<View style={tw`mt-3`}>
|
||||
{products.length > 0 ? (
|
||||
<View style={tw`flex-row flex-wrap justify-between`}>
|
||||
{visible.map((product: any) => (
|
||||
|
|
@ -312,7 +311,6 @@ const TagScene = memo(({
|
|||
)}
|
||||
{hasMore && (
|
||||
<MyTouchableOpacity
|
||||
testID={`tag-show-more-${tagId}`}
|
||||
style={tw`self-center mt-1 mb-2 px-5 py-2.5 rounded-full bg-brand500 shadow-sm`}
|
||||
activeOpacity={0.85}
|
||||
onPress={() => onToggleExpand(tagId)}
|
||||
|
|
@ -328,7 +326,7 @@ const ExploreProductItem = memo(({ item, onPress }: ProductItemProps) => {
|
|||
const handlePress = useCallback(() => onPress(item.id), [item.id, onPress]);
|
||||
|
||||
return (
|
||||
<View style={tw`mb-3`} testID={`tag-product-${item.id}`}>
|
||||
<View style={tw`mb-3`}>
|
||||
<ProductCard
|
||||
item={item}
|
||||
itemWidth={heroItemWidth}
|
||||
|
|
@ -698,7 +696,6 @@ export default function Dashboard() {
|
|||
style={searchBarContainerStyle}
|
||||
>
|
||||
<SearchBar
|
||||
testID="home-search"
|
||||
value={""}
|
||||
onChangeText={() => { }}
|
||||
onPress={handleSearchPress}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,6 @@ export default function SearchResults() {
|
|||
<View style={tw`pt-4 pb-2 px-4`}>
|
||||
<SearchBar
|
||||
ref={searchInputRef}
|
||||
testID="search-input"
|
||||
value={inputQuery}
|
||||
onChangeText={setInputQuery}
|
||||
onSubmitEditing={handleSearch}
|
||||
|
|
|
|||
|
|
@ -403,7 +403,6 @@ export default function OrderDetails() {
|
|||
|
||||
<MyText style={tw`text-gray-700 font-medium mb-2`}>Reason for cancellation</MyText>
|
||||
<TextInput
|
||||
testID="cancel-reason"
|
||||
style={tw`bg-gray-50 border border-gray-200 rounded-xl p-4 min-h-24 text-base text-gray-800 mb-6`}
|
||||
value={cancelReason}
|
||||
onChangeText={setCancelReason}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import { Stack } from "expo-router";
|
|||
import "react-native-reanimated";
|
||||
|
||||
import { useColorScheme } from "@/hooks/useColorScheme";
|
||||
import { Appearance, StatusBar, View, LogBox } from "react-native";
|
||||
import { Appearance, StatusBar, View } from "react-native";
|
||||
import { QueryClientProvider } from "@tanstack/react-query";
|
||||
import { theme , MyStatusBar } from "common-ui";
|
||||
import queryClient from "@/utils/queryClient";
|
||||
|
|
@ -31,13 +31,6 @@ import React from "react";
|
|||
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
||||
import NotifChecker from "@/services/notif-service/notif-checker";
|
||||
|
||||
// Silence dev warnings/errors in LogBox. The "Open debugger to view warnings"
|
||||
// toast overlays the bottom of the UI and intercepts taps (e.g. tab bar /
|
||||
// bottom-sheet buttons), which breaks E2E flows.
|
||||
if (__DEV__) {
|
||||
LogBox.ignoreAllLogs(true);
|
||||
}
|
||||
|
||||
export default function RootLayout() {
|
||||
const colorScheme = useColorScheme();
|
||||
const [loaded] = useFonts({
|
||||
|
|
|
|||
|
|
@ -160,10 +160,9 @@ const CheckoutAddressSelector: React.FC<AddressSelectorProps> = ({
|
|||
decelerationRate="fast"
|
||||
snapToInterval={CARD_WIDTH}
|
||||
>
|
||||
{sortedAddresses.map((address, index) => (
|
||||
{sortedAddresses.map((address) => (
|
||||
<TouchableOpacity
|
||||
key={address.id}
|
||||
testID={`address-option-${index}`}
|
||||
onPress={() => {
|
||||
onAddressSelect(address.id);
|
||||
resetScrollToLeft();
|
||||
|
|
|
|||
|
|
@ -328,8 +328,8 @@ const PaymentAndOrderComponent: React.FC<PaymentAndOrderProps> = ({
|
|||
|
||||
{/* Bottom Action Bar */}
|
||||
<View style={tw`bg-white p-5 rounded-2xl shadow-sm mb-4 border border-gray-100`}>
|
||||
{!selectedAddress && (
|
||||
<View testID="select-address-error" style={tw`bg-red-50 p-3 rounded-lg mb-3 flex-row items-center`}>
|
||||
{!selectedAddress && (
|
||||
<View style={tw`bg-red-50 p-3 rounded-lg mb-3 flex-row items-center`}>
|
||||
<MaterialIcons name="error-outline" size={16} color="#EF4444" style={tw`mr-2`} />
|
||||
<MyText style={tw`text-red-600 text-sm font-medium`}>
|
||||
Please select a delivery address to place order
|
||||
|
|
@ -337,7 +337,6 @@ const PaymentAndOrderComponent: React.FC<PaymentAndOrderProps> = ({
|
|||
</View>
|
||||
)}
|
||||
<MyTouchableOpacity
|
||||
testID="place-order-button"
|
||||
style={tw`bg-brand500 py-4 rounded-xl items-center shadow-md ${!selectedAddress ? 'opacity-50' : ''}`}
|
||||
disabled={!selectedAddress}
|
||||
onPress={handlePlaceOrder}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,6 @@ const ProductCard: React.FC<ProductCardProps> = ({
|
|||
return (
|
||||
<ContainerComp>
|
||||
<MyTouchableOpacity
|
||||
testID="product-card"
|
||||
style={[
|
||||
tw`bg-white overflow-hidden border border-gray-200`,
|
||||
isHero ? tw`rounded-xl pb-1.5` : tw`rounded-2xl pb-2`,
|
||||
|
|
@ -206,7 +205,6 @@ const ProductCard: React.FC<ProductCardProps> = ({
|
|||
<MiniQuantifier value={quantity} onChange={handleQuantityChange} step={item.incrementStep} />
|
||||
) : (
|
||||
<MyTouchableOpacity
|
||||
testID="add-to-cart-icon"
|
||||
style={isHero ? tw`w-7 h-7 rounded-full bg-white items-center justify-center shadow-md` : tw`w-8 h-8 rounded-full bg-white items-center justify-center shadow-md`}
|
||||
onPress={() => handleQuantityChange(1)}
|
||||
activeOpacity={0.8}
|
||||
|
|
|
|||
|
|
@ -958,7 +958,6 @@ export default function CartPage({ isFlashDelivery = false }: FlashDeliveryProps
|
|||
<MyText style={tw`text-gray-700 font-bold`}>Shop More</MyText>
|
||||
</MyTouchableOpacity>
|
||||
<MyTouchableOpacity
|
||||
testID="checkout-button"
|
||||
style={tw`flex-1 bg-brand500 py-3.5 rounded-xl items-center shadow-md flex-row justify-center`}
|
||||
onPress={() => {
|
||||
const availableItems = cartItems
|
||||
|
|
|
|||
|
|
@ -211,7 +211,6 @@ const FloatingCartBar: React.FC<FloatingCartBarProps> = ({
|
|||
</View>
|
||||
|
||||
<MyTouchableOpacity
|
||||
testID="go-to-cart"
|
||||
style={tw`bg-white px-3 py-2 rounded-2xl shadow-lg shadow-black/20`}
|
||||
onPress={() => router.push(
|
||||
isFlashDelivery
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { useCentralProductStore } from '@/src/store/centralProductStore';
|
||||
import { useCentralSlotStore } from '@/src/store/centralSlotStore';
|
||||
import { Alert } from 'react-native';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import dayjs from 'dayjs';
|
||||
import { useQuery, useMutation, useQueryClient, UseQueryResult, UseMutationResult } from '@tanstack/react-query';
|
||||
import type { CartData as SharedCartData, ProductSummaryCore } from '@packages/shared';
|
||||
import { StorageServiceCasual } from 'common-ui/src/services/StorageServiceCasual';
|
||||
|
|
@ -246,49 +244,6 @@ export function useGetCart(options: UseGetCartOptions = {}, cartType: CartType =
|
|||
};
|
||||
}
|
||||
|
||||
export function useReconcileCartSlots() {
|
||||
const productSlotsMap = useCentralSlotStore((state) => state.productSlotsMap);
|
||||
const isSlotsLoaded = useCentralSlotStore((state) => state.isSlotsLoaded);
|
||||
const queryClient = useQueryClient();
|
||||
const hasRun = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isSlotsLoaded || hasRun.current) return;
|
||||
hasRun.current = true;
|
||||
|
||||
(async () => {
|
||||
const items = await getLocalCart("regular");
|
||||
if (items.length === 0) return;
|
||||
|
||||
let changed = false;
|
||||
const nextItems: LocalCartItem[] = [];
|
||||
|
||||
for (const item of items) {
|
||||
const validSlots = productSlotsMap[item.skuId]?.slots ?? [];
|
||||
|
||||
if (validSlots.some((slot) => slot.id === item.slotId)) {
|
||||
nextItems.push(item);
|
||||
continue;
|
||||
}
|
||||
|
||||
const nearestSlot = [...validSlots].sort(
|
||||
(a, b) => dayjs(a.deliveryTime).valueOf() - dayjs(b.deliveryTime).valueOf()
|
||||
)[0];
|
||||
|
||||
if (nearestSlot) {
|
||||
nextItems.push({ ...item, slotId: nearestSlot.id });
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
await saveLocalCart(nextItems, "regular");
|
||||
queryClient.invalidateQueries({ queryKey: ["local-cart-regular"] });
|
||||
}
|
||||
})();
|
||||
}, [isSlotsLoaded, productSlotsMap, queryClient]);
|
||||
}
|
||||
|
||||
export function useAddToCart(options: MutationOptions<LocalCartItem[], AddToCartVariables> = {}, cartType: CartType = "regular"): UseAddToCartReturn {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
|
|
|
|||
|
|
@ -17,17 +17,4 @@ config.resolver.extraNodeModules = {
|
|||
'global-shared': path.resolve(__dirname, '../../packages/shared'),
|
||||
};
|
||||
|
||||
// Never bundle the test folder. It is tooled by Jest (see tests/jest.config.js)
|
||||
// and excluded from EAS uploads (.easignore); blocking it here makes an
|
||||
// accidental production import fail loudly instead of silently shipping.
|
||||
const escapeForRegExp = (value) =>
|
||||
value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
|
||||
config.resolver.blockList = [
|
||||
...(config.resolver.blockList
|
||||
? [].concat(config.resolver.blockList)
|
||||
: []),
|
||||
new RegExp(`^${escapeForRegExp(path.resolve(__dirname, 'tests'))}[/\\\\].*$`),
|
||||
];
|
||||
|
||||
module.exports = config;
|
||||
|
|
|
|||
|
|
@ -8,10 +8,7 @@
|
|||
"android": "expo run:android",
|
||||
"ios": "expo run:ios",
|
||||
"web": "expo start --web",
|
||||
"lint": "expo lint",
|
||||
"test": "jest --config tests/jest.config.js",
|
||||
"test:watch": "jest --config tests/jest.config.js --watch",
|
||||
"test:typecheck": "tsc --noEmit --project tsconfig.json"
|
||||
"lint": "expo lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@expo/vector-icons": "^14.1.0",
|
||||
|
|
@ -74,16 +71,10 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@testing-library/react-native": "^13",
|
||||
"@types/jest": "^29",
|
||||
"@types/react": "~19.0.10",
|
||||
"@types/react-native-razorpay": "^2.2.6",
|
||||
"babel-preset-expo": "~13.0.0",
|
||||
"eslint": "^9.25.0",
|
||||
"eslint-config-expo": "~9.2.0",
|
||||
"jest": "~29.7.0",
|
||||
"jest-expo": "~53.0.0",
|
||||
"react-test-renderer": "19.0.0",
|
||||
"typescript": "~5.8.3"
|
||||
},
|
||||
"private": true
|
||||
|
|
|
|||
|
|
@ -162,7 +162,6 @@ export default function AddToCartDialog() {
|
|||
{availableSlots.map((slot: any) => (
|
||||
<MyTouchableOpacity
|
||||
key={slot.id}
|
||||
testID={`slot-${dayjs(slot.deliveryTime).format('YYYY-MM-DD-HH-mm')}`}
|
||||
style={tw`flex-row items-start mb-4 bg-gray-50 p-4 rounded-xl border border-gray-100 ${selectedSlotId === slot.id ? 'border-brand500' : 'border-gray-100'
|
||||
}`}
|
||||
onPress={() => {
|
||||
|
|
@ -242,7 +241,6 @@ export default function AddToCartDialog() {
|
|||
|
||||
<View style={tw`flex-row gap-3 mt-4 pb-12`}>
|
||||
<MyTouchableOpacity
|
||||
testID="add-to-cart-confirm"
|
||||
style={tw`flex-1 bg-brand500 py-3.5 rounded-xl items-center ${(!selectedSlotId && !selectedFlashDelivery) ? 'opacity-50' : ''}`}
|
||||
onPress={handleAddToCart}
|
||||
disabled={(addToCart.isLoading || updateCartItem.isLoading) || (!selectedSlotId && !selectedFlashDelivery)}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,6 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
|
|||
{({ handleChange, handleBlur, handleSubmit, values, errors, touched, setFieldValue }) => (
|
||||
<View style={tw`flex-col gap-2`}>
|
||||
<MyTextInput
|
||||
testID="address-name"
|
||||
placeholder="Name"
|
||||
shrunkPadding={true}
|
||||
onChangeText={handleChange('name')}
|
||||
|
|
@ -123,7 +122,6 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
|
|||
{touched.name && errors.name && <MyText style={tw`text-red-500 mb-2`}>{errors.name}</MyText>}
|
||||
|
||||
<MyTextInput
|
||||
testID="address-phone"
|
||||
placeholder="Phone"
|
||||
shrunkPadding={true}
|
||||
keyboardType="phone-pad"
|
||||
|
|
@ -134,7 +132,6 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
|
|||
{touched.phone && errors.phone && <MyText style={tw`text-red-500 mb-2`}>{errors.phone}</MyText>}
|
||||
|
||||
<MyTextInput
|
||||
testID="address-line1"
|
||||
placeholder="Address Line 1"
|
||||
shrunkPadding={true}
|
||||
onChangeText={handleChange('addressLine1')}
|
||||
|
|
@ -230,7 +227,6 @@ const AddressForm: React.FC<AddressFormProps> = ({ onSuccess, initialValues, isE
|
|||
</View>
|
||||
|
||||
<MyTouchableOpacity
|
||||
testID="address-submit"
|
||||
style={tw`bg-indigo-600 p-3 rounded ${isSubmitting ? 'opacity-50' : ''}`}
|
||||
onPress={() => handleSubmit()}
|
||||
disabled={isSubmitting}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
import React from 'react';
|
||||
import { useInitializeCentralSlotStore } from '@/src/store/centralSlotStore';
|
||||
import { useInitializeCentralProductStore } from '@/src/store/centralProductStore';
|
||||
import { useReconcileCartSlots } from '@/hooks/cart-query-hooks';
|
||||
import type { ReactParentComponent } from '@packages/shared';
|
||||
|
||||
export default function CentralStoreInitializer({ children }: ReactParentComponent) {
|
||||
useInitializeCentralSlotStore();
|
||||
useInitializeCentralProductStore();
|
||||
useReconcileCartSlots();
|
||||
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
[
|
||||
{
|
||||
"result": {
|
||||
"data": {
|
||||
"freeDeliveryThreshold": 249,
|
||||
"deliveryCharge": 15,
|
||||
"flashFreeDeliveryThreshold": 399,
|
||||
"flashDeliveryCharge": 39,
|
||||
"popularItems": "40,109,9,75,98,6,24,59",
|
||||
"versionNum": "1.2.0",
|
||||
"playStoreUrl": "https://info.freshyo.in/qr-based-download",
|
||||
"appStoreUrl": "https://info.freshyo.in/qr-based-download",
|
||||
"webViewHtml": null,
|
||||
"webviewHtml": null,
|
||||
"isWebviewClosable": true,
|
||||
"isFlashDeliveryEnabled": false,
|
||||
"supportMobile": "9000885620",
|
||||
"supportEmail": "qushammohd@gmail.com",
|
||||
"assetsDomain": "https://assets.freshyo.in/",
|
||||
"apiCacheKey": "api-cache",
|
||||
"cacheVersion": 755,
|
||||
"availabilityVersionNum": 72,
|
||||
"slotsVersionNum": 401
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
/**
|
||||
* Integration tests for app/(drawer)/(tabs)/home/index.tsx
|
||||
*
|
||||
* API responses are mocked at the network layer:
|
||||
* - common.essentialConsts -> tests/__fixtures__/essentialConsts.json
|
||||
* - assets CDN -> tests/mocks/mock-*-response.json
|
||||
*
|
||||
* Runner: `bun run test` (or `bun run test:watch`) from apps/user-ui.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import {
|
||||
fireEvent,
|
||||
render,
|
||||
screen,
|
||||
waitFor,
|
||||
within,
|
||||
} from '@testing-library/react-native'
|
||||
import { RefreshProvider } from 'common-ui'
|
||||
|
||||
import Dashboard from '@/app/(drawer)/(tabs)/home/index'
|
||||
import { trpc, trpcClient } from '@/src/trpc-client'
|
||||
import productsResponse from './mocks/mock-products-response.json'
|
||||
import { PRODUCTS_URL, setupApiMocks } from './mocks/api'
|
||||
|
||||
// The tag grid renders at most this many items before its "Show More" button
|
||||
// expands it (see the products.slice(0, 6) in TagScene).
|
||||
const TAG_GRID_PREVIEW = 6
|
||||
|
||||
const knownProductIds = new Set(productsResponse.products.map((p) => p.id))
|
||||
const tags = productsResponse.tags
|
||||
|
||||
/** Products a tag points at that actually exist in the products cache. */
|
||||
const productIdsForTag = (tag: (typeof tags)[number]) =>
|
||||
tag.productIds.filter((id) => knownProductIds.has(id))
|
||||
|
||||
function renderHome() {
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: { queries: { retry: false, gcTime: 0 } },
|
||||
})
|
||||
|
||||
return render(
|
||||
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<RefreshProvider queryClient={queryClient}>
|
||||
<Dashboard />
|
||||
</RefreshProvider>
|
||||
</QueryClientProvider>
|
||||
</trpc.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
describe('Home page', () => {
|
||||
let api: ReturnType<typeof setupApiMocks>
|
||||
|
||||
beforeEach(() => {
|
||||
api = setupApiMocks()
|
||||
})
|
||||
|
||||
it('requests the products cache url derived from common.essentialConsts', async () => {
|
||||
renderHome()
|
||||
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
api.fetchMock.mock.calls.some(([url]) =>
|
||||
String(url).includes('common.essentialConsts')
|
||||
)
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
await waitFor(() => {
|
||||
expect(api.axiosGet).toHaveBeenCalledWith(PRODUCTS_URL)
|
||||
})
|
||||
})
|
||||
|
||||
it('shows a tab for every tag', async () => {
|
||||
renderHome()
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId(`tag-tab-${tags[0].id}`)).toBeTruthy()
|
||||
})
|
||||
|
||||
for (const tag of tags) {
|
||||
const tab = screen.getByTestId(`tag-tab-${tag.id}`)
|
||||
expect(within(tab).getByText(tag.tagName)).toBeVisible()
|
||||
}
|
||||
})
|
||||
|
||||
it('shows every product of every tag, expanding each grid once', async () => {
|
||||
renderHome()
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId(`tag-grid-${tags[0].id}`)).toBeTruthy()
|
||||
})
|
||||
|
||||
for (const tag of tags) {
|
||||
fireEvent.press(screen.getByTestId(`tag-tab-${tag.id}`))
|
||||
|
||||
const expected = productIdsForTag(tag)
|
||||
expect(expected.length).toBeGreaterThan(0)
|
||||
|
||||
for (const id of expected.slice(0, TAG_GRID_PREVIEW)) {
|
||||
expect(screen.getByTestId(`tag-product-${id}`)).toBeVisible()
|
||||
}
|
||||
|
||||
if (expected.length <= TAG_GRID_PREVIEW) continue
|
||||
|
||||
// Items past the preview are withheld until the grid is expanded.
|
||||
expect(
|
||||
screen.queryByTestId(`tag-product-${expected[TAG_GRID_PREVIEW]}`)
|
||||
).toBeNull()
|
||||
|
||||
fireEvent.press(screen.getByTestId(`tag-show-more-${tag.id}`))
|
||||
|
||||
for (const id of expected) {
|
||||
expect(screen.getByTestId(`tag-product-${id}`)).toBeVisible()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
it.todo('shows every product returned by the products cache')
|
||||
it.todo('shows the store list')
|
||||
it.todo('shows the upcoming delivery slots')
|
||||
})
|
||||
7
apps/user-ui/tests/jest-env.d.ts
vendored
7
apps/user-ui/tests/jest-env.d.ts
vendored
|
|
@ -1,7 +0,0 @@
|
|||
/// <reference types="jest" />
|
||||
|
||||
// Declares the Jest globals (describe, it, expect, jest, ...) for the tests in
|
||||
// this folder. @types/jest is a devDependency, but making the reference explicit
|
||||
// means the globals are declared by a file inside the project rather than
|
||||
// relying on ambient @types auto-inclusion, so editors resolve them even when a
|
||||
// file falls back to an inferred project.
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
const path = require('path')
|
||||
|
||||
const appRoot = path.resolve(__dirname, '..')
|
||||
|
||||
/**
|
||||
* Jest project for apps/user-ui integration tests.
|
||||
*
|
||||
* Kept out of the app build three ways:
|
||||
* 1. .easignore (tests/ never uploaded to EAS)
|
||||
* 2. metro.config.js resolver.blockList (never bundled)
|
||||
* 3. tsconfig.json exclude + tests/tsconfig.json (separate typecheck scope)
|
||||
*/
|
||||
module.exports = {
|
||||
preset: 'jest-expo',
|
||||
rootDir: appRoot,
|
||||
roots: ['<rootDir>/tests'],
|
||||
testMatch: ['<rootDir>/tests/**/*.test.ts', '<rootDir>/tests/**/*.test.tsx'],
|
||||
setupFiles: ['<rootDir>/tests/setup.ts'],
|
||||
clearMocks: true,
|
||||
moduleNameMapper: {
|
||||
'^@/(.*)$': '<rootDir>/$1',
|
||||
'^@backend/(.*)$': '<rootDir>/../backend/src/$1',
|
||||
'^shared-types$': '<rootDir>/../shared-types',
|
||||
'^@packages/shared$': '<rootDir>/../../packages/shared',
|
||||
'^@packages/shared/(.*)$': '<rootDir>/../../packages/shared/$1',
|
||||
'^global-shared$': '<rootDir>/../../packages/shared',
|
||||
'^global-shared/(.*)$': '<rootDir>/../../packages/shared/$1',
|
||||
'^common-ui$': '<rootDir>/../../packages/ui',
|
||||
'^common-ui/(.*)$': '<rootDir>/../../packages/ui/$1',
|
||||
},
|
||||
transformIgnorePatterns: [
|
||||
'node_modules/(?!(?:.pnpm/)?(' +
|
||||
[
|
||||
'(jest-)?react-native',
|
||||
'@react-native(-community)?',
|
||||
'expo(nent)?',
|
||||
'@expo(nent)?/.*',
|
||||
'@expo-google-fonts/.*',
|
||||
'react-navigation',
|
||||
'@react-navigation/.*',
|
||||
'@sentry/react-native',
|
||||
'native-base',
|
||||
'react-native-svg',
|
||||
'react-native-gesture-handler',
|
||||
'react-native-reanimated',
|
||||
'react-native-safe-area-context',
|
||||
'react-native-screens',
|
||||
'@trpc/.*',
|
||||
'@tanstack/.*',
|
||||
'twrnc',
|
||||
'zod',
|
||||
'@testing-library/react-native',
|
||||
].join('|') +
|
||||
'))',
|
||||
],
|
||||
}
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
/**
|
||||
* Network-layer mocks for the user-ui tests.
|
||||
*
|
||||
* Everything the home page fetches goes through one of two doors:
|
||||
* - tRPC -> global.fetch (common.essentialConsts, ...)
|
||||
* - axios -> the assets CDN (products.json, stores.json, slots.json, availability.json)
|
||||
*
|
||||
* Both are stubbed here and both fail loudly on an unmocked URL, so a new
|
||||
* dependency introduced by app code surfaces as a test failure instead of a
|
||||
* silent empty render.
|
||||
*
|
||||
* The tRPC URL is matched on the procedure path rather than the host, because
|
||||
* BASE_API_URL (packages/ui/index.ts) is a local address during development.
|
||||
* `jest.mock('axios')` lives in tests/setup.ts so it is registered before any
|
||||
* app module imports axios.
|
||||
*
|
||||
* Fixtures are imported as JSON rather than read with `fs`: importing a Node
|
||||
* builtin pulls @types/node into the typecheck program, which flips
|
||||
* `setTimeout` from `number` to `NodeJS.Timeout` and breaks unrelated app types.
|
||||
*
|
||||
* NOTE: mock-slots-response.json is a snapshot of a real day (see the
|
||||
* deliveryTime values). The home page drops past slots, so those fixtures need
|
||||
* refreshing once their dates fall behind.
|
||||
*/
|
||||
|
||||
import essentialConsts from '../__fixtures__/essentialConsts.json'
|
||||
import availability from './mock-availability-response.json'
|
||||
import products from './mock-products-response.json'
|
||||
import slots from './mock-slots-response.json'
|
||||
import stores from './mock-stores-response.json'
|
||||
|
||||
export const ESSENTIAL_CONSTS_URL =
|
||||
'https://worker.freshyo.in/api/trpc/common.essentialConsts?batch=1&input=%7B%220%22%3A%7B%22json%22%3Anull%2C%22meta%22%3A%7B%22values%22%3A%5B%22undefined%22%5D%7D%7D%7D'
|
||||
|
||||
// Derived by useCacheUrl / useAvailabilityCacheUrl / useSlotsCacheUrl from the
|
||||
// essentialConsts payload above (assetsDomain, apiCacheKey, cacheVersion,
|
||||
// availabilityVersionNum, slotsVersionNum).
|
||||
export const PRODUCTS_URL =
|
||||
'https://assets.freshyo.in/api-cache/v-755/products.json'
|
||||
export const AVAILABILITY_URL =
|
||||
'https://assets.freshyo.in/av-72/availability.json'
|
||||
export const STORES_URL = 'https://assets.freshyo.in/api-cache/v-755/stores.json'
|
||||
export const SLOTS_URL = 'https://assets.freshyo.in/slots/v-401/slots.json?v=123'
|
||||
|
||||
/** Route a CDN file name to its mock response. */
|
||||
const mockForCacheFile = (url: string): unknown => {
|
||||
if (url.includes('products.json')) return products
|
||||
if (url.includes('stores.json')) return stores
|
||||
if (url.includes('slots.json')) return slots
|
||||
if (url.includes('availability.json')) return availability
|
||||
throw new Error(`[tests] unmocked assets request: ${url}`)
|
||||
}
|
||||
|
||||
const jsonResponse = (body: unknown) => ({
|
||||
ok: true,
|
||||
status: 200,
|
||||
statusText: 'OK',
|
||||
headers: new Map(),
|
||||
url: '',
|
||||
json: async () => body,
|
||||
text: async () => JSON.stringify(body),
|
||||
})
|
||||
|
||||
/**
|
||||
* Install the fetch + axios stubs and return the handles for assertions.
|
||||
* Call from beforeEach so each test starts from a clean call history.
|
||||
*/
|
||||
export function setupApiMocks() {
|
||||
const axios = require('axios')
|
||||
|
||||
axios.get.mockImplementation(async (url: string) => ({
|
||||
data: mockForCacheFile(url),
|
||||
status: 200,
|
||||
statusText: 'OK',
|
||||
headers: {},
|
||||
config: {},
|
||||
}))
|
||||
|
||||
const fetchMock = jest.fn(async (url: string) => {
|
||||
if (url.includes('common.essentialConsts')) {
|
||||
return jsonResponse(essentialConsts)
|
||||
}
|
||||
|
||||
throw new Error(`[tests] unmocked fetch: ${url}`)
|
||||
})
|
||||
|
||||
;(global as unknown as { fetch: unknown }).fetch = fetchMock
|
||||
|
||||
return { fetchMock, axiosGet: axios.get }
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,124 +0,0 @@
|
|||
{
|
||||
"stores": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Meat Store",
|
||||
"description": "\"Fresh, high-quality meat sourced from trusted suppliers and hygienically processed. Cut fresh, packed safely, and delivered to your doorstep.\"",
|
||||
"signedImageUrl": "https://assets.freshyo.in/store-images/1766052073748.png",
|
||||
"productCount": 39,
|
||||
"sampleProducts": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Chicken Liver",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1768478127128-0"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Chicken Breast 500 g",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1768397780093-0"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Chicken Lollipops",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1768475599800-0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "The Fruit Store",
|
||||
"description": "\"Fresh, juicy fruits handpicked for quality and taste. Naturally ripened, carefully packed, and delivered fresh to your home.\"",
|
||||
"signedImageUrl": "https://assets.freshyo.in/store-images/1766053828604.png",
|
||||
"productCount": 35,
|
||||
"sampleProducts": [
|
||||
{
|
||||
"id": 6,
|
||||
"name": "Apple ( pack of 3) ",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1768640936747-0"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "Banana",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1768640009078-0"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Kiwi",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1768647119198-0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Vegetables",
|
||||
"description": "Fresh, handpicked vegetables delivered straight from trusted farms to your home. Enjoy clean, high-quality sabzi every day-healthy, natural, and full of freshness.",
|
||||
"signedImageUrl": "https://assets.freshyo.in/store-images/1766051618139.png",
|
||||
"productCount": 46,
|
||||
"sampleProducts": [
|
||||
{
|
||||
"id": 5,
|
||||
"name": "Cucumber(Kheera)",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1768710099841-0"
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"name": "Arvi (Arbi) – Colocasia Root",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1769397372526-0"
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"name": "Tomato ",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1768640233068-0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Fruits Juices ",
|
||||
"description": "",
|
||||
"signedImageUrl": "https://assets.freshyo.in/store-images/1773121148038.png",
|
||||
"productCount": 22,
|
||||
"sampleProducts": [
|
||||
{
|
||||
"id": 104,
|
||||
"name": "Green grape fresh juice",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1773126251435-0"
|
||||
},
|
||||
{
|
||||
"id": 105,
|
||||
"name": "Fresh fig juice (anjeer) ",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1773126524403-0"
|
||||
},
|
||||
{
|
||||
"id": 106,
|
||||
"name": "Chikoo (sapota)fresh juice",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1773127805418-0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "Dry Fruits store ",
|
||||
"description": "",
|
||||
"signedImageUrl": "https://assets.freshyo.in/store-images/1784697413573.jpg",
|
||||
"productCount": 7,
|
||||
"sampleProducts": [
|
||||
{
|
||||
"id": 129,
|
||||
"name": "Cashew (kaju) ",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1784220823113.jpg"
|
||||
},
|
||||
{
|
||||
"id": 130,
|
||||
"name": "Badam",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1784698463282.jpg"
|
||||
},
|
||||
{
|
||||
"id": 131,
|
||||
"name": "Raisins (kishmish) ",
|
||||
"signedImageUrl": "https://assets.freshyo.in/product-images/1784221386651.jpg"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
/**
|
||||
* Shared Jest setup for apps/user-ui.
|
||||
*
|
||||
* Only the native/context dependencies that cannot run under a plain Jest
|
||||
* environment are stubbed here. Everything else (components, stores, hooks)
|
||||
* stays real so tests exercise the actual wiring.
|
||||
*
|
||||
* Note: no `typeof import('react-native')` type expressions below. Loading the
|
||||
* RN ambient globals from a type position here reverses their precedence with
|
||||
* @types/node's, which flips `setTimeout` from `number` to `NodeJS.Timeout` and
|
||||
* fails typecheck in unrelated app files (packages/ui/src/components/
|
||||
* bottom-dropdown.tsx).
|
||||
*/
|
||||
|
||||
import type { ReactNode } from 'react'
|
||||
|
||||
jest.mock('expo-router', () => ({
|
||||
useRouter: () => ({
|
||||
push: jest.fn(),
|
||||
replace: jest.fn(),
|
||||
back: jest.fn(),
|
||||
navigate: jest.fn(),
|
||||
}),
|
||||
router: {
|
||||
push: jest.fn(),
|
||||
replace: jest.fn(),
|
||||
back: jest.fn(),
|
||||
},
|
||||
useLocalSearchParams: () => ({}),
|
||||
useGlobalSearchParams: () => ({}),
|
||||
useFocusEffect: () => {},
|
||||
Link: ({ children }: { children?: ReactNode }) => children ?? null,
|
||||
}))
|
||||
|
||||
/**
|
||||
* Refresh plumbing, irrelevant to what these tests assert.
|
||||
* `useMarkDataFetchers` runs `useFocusEffect`, which throws without a
|
||||
* NavigationContainer. These are mocked by their own module paths rather than
|
||||
* partially mocking the `common-ui` index: several index components import
|
||||
* back from `common-ui` (button.tsx -> common-ui), so spreading
|
||||
* `jest.requireActual('common-ui')` walks a half-initialised module and throws.
|
||||
*/
|
||||
jest.mock('common-ui/hooks/useMarkDataFetchers', () => ({
|
||||
__esModule: true,
|
||||
useMarkDataFetchers: () => {},
|
||||
}))
|
||||
|
||||
jest.mock('common-ui/hooks/useManualRefresh', () => ({
|
||||
__esModule: true,
|
||||
default: () => {},
|
||||
}))
|
||||
|
||||
// Registered here (not in the test files) so it is in place before any app
|
||||
// module imports axios. Implementations are set in tests/mocks/api.ts.
|
||||
jest.mock('axios')
|
||||
|
||||
/**
|
||||
* Auth is out of scope for these tests. `useUserDetails` throws without an
|
||||
* AuthProvider (which would drag in secure-store, tRPC login and redirect
|
||||
* handling), so the context is stubbed with the signed-out shape.
|
||||
*/
|
||||
jest.mock('@/src/contexts/AuthContext', () => ({
|
||||
AuthProvider: ({ children }: { children?: ReactNode }) => children ?? null,
|
||||
useAuth: () => ({
|
||||
user: null,
|
||||
userDetails: null,
|
||||
isAuthenticated: false,
|
||||
isLoading: false,
|
||||
token: null,
|
||||
}),
|
||||
useUserDetails: () => null,
|
||||
}))
|
||||
|
||||
/**
|
||||
* Cart hooks import this deep path directly (not via the common-ui index), and
|
||||
* the real service talks to expo-secure-store. In-memory map instead; the cart
|
||||
* starts empty, which is the cold-start path these tests exercise.
|
||||
*/
|
||||
jest.mock('common-ui/src/services/StorageServiceCasual', () => {
|
||||
const store = new Map<string, string>()
|
||||
|
||||
return {
|
||||
StorageServiceCasual: {
|
||||
getItem: jest.fn(async (key: string) => store.get(key) ?? null),
|
||||
setItem: jest.fn(async (key: string, value: string) => {
|
||||
store.set(key, value)
|
||||
return true
|
||||
}),
|
||||
removeItem: jest.fn(async (key: string) => {
|
||||
store.delete(key)
|
||||
return true
|
||||
}),
|
||||
clearAll: jest.fn(async (keys: string[]) => {
|
||||
keys.forEach((key) => store.delete(key))
|
||||
return true
|
||||
}),
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Freeze the clock for every test. The home page is time-sensitive — it drops
|
||||
* slots whose deliveryTime is not after `dayjs()` and flags slots "closing
|
||||
* soon" within 4 hours — while the slot mocks carry fixed deliveryTime values.
|
||||
* A drifting wall clock therefore makes those assertions flaky.
|
||||
*
|
||||
* Frozen at suite start rather than a hard-coded instant, so the fixed slot
|
||||
* dates in the mocks stay in the future. Use `jest.advanceTimersByTime()` /
|
||||
* `jest.setSystemTime()` in a test that needs to move through time.
|
||||
*/
|
||||
jest.useFakeTimers({ now: Date.now() })
|
||||
|
|
@ -47,8 +47,5 @@
|
|||
".expo/types/**/*.ts",
|
||||
"expo-env.d.ts",
|
||||
"../../packages/shared"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
406
bun.lock
406
bun.lock
|
|
@ -305,16 +305,10 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@testing-library/react-native": "^13",
|
||||
"@types/jest": "^29",
|
||||
"@types/react": "~19.0.10",
|
||||
"@types/react-native-razorpay": "^2.2.6",
|
||||
"babel-preset-expo": "~13.0.0",
|
||||
"eslint": "^9.25.0",
|
||||
"eslint-config-expo": "~9.2.0",
|
||||
"jest": "~29.7.0",
|
||||
"jest-expo": "~53.0.0",
|
||||
"react-test-renderer": "19.0.0",
|
||||
"typescript": "~5.8.3",
|
||||
},
|
||||
},
|
||||
|
|
@ -702,8 +696,6 @@
|
|||
|
||||
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
|
||||
|
||||
"@bcoe/v8-coverage": ["@bcoe/v8-coverage@0.2.3", "", {}, "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw=="],
|
||||
|
||||
"@bramus/specificity": ["@bramus/specificity@2.4.2", "", { "dependencies": { "css-tree": "^3.0.0" }, "bin": { "specificity": "bin/cli.js" } }, "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw=="],
|
||||
|
||||
"@callstack/react-theme-provider": ["@callstack/react-theme-provider@3.0.9", "", { "dependencies": { "deepmerge": "^3.2.0", "hoist-non-react-statics": "^3.3.0" }, "peerDependencies": { "react": ">=16.3.0" } }, "sha512-tTQ0uDSCL0ypeMa8T/E9wAZRGKWj8kXP7+6RYgPTfOPs9N07C9xM8P02GJ3feETap4Ux5S69D9nteq9mEj86NA=="],
|
||||
|
|
@ -964,40 +956,14 @@
|
|||
|
||||
"@istanbuljs/schema": ["@istanbuljs/schema@0.1.3", "", {}, "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="],
|
||||
|
||||
"@jest/console": ["@jest/console@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "jest-message-util": "^29.7.0", "jest-util": "^29.7.0", "slash": "^3.0.0" } }, "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg=="],
|
||||
|
||||
"@jest/core": ["@jest/core@29.7.0", "", { "dependencies": { "@jest/console": "^29.7.0", "@jest/reporters": "^29.7.0", "@jest/test-result": "^29.7.0", "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.7.0", "jest-config": "^29.7.0", "jest-haste-map": "^29.7.0", "jest-message-util": "^29.7.0", "jest-regex-util": "^29.6.3", "jest-resolve": "^29.7.0", "jest-resolve-dependencies": "^29.7.0", "jest-runner": "^29.7.0", "jest-runtime": "^29.7.0", "jest-snapshot": "^29.7.0", "jest-util": "^29.7.0", "jest-validate": "^29.7.0", "jest-watcher": "^29.7.0", "micromatch": "^4.0.4", "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"] }, "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg=="],
|
||||
|
||||
"@jest/create-cache-key-function": ["@jest/create-cache-key-function@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3" } }, "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA=="],
|
||||
|
||||
"@jest/diff-sequences": ["@jest/diff-sequences@30.5.0", "", {}, "sha512-OsqBjHXCn8cadasoAZBP6nWYvMsRhpMzGXTpxJ5aO04NlbdhIz+FVe3q49l0AwVhsz/cEmIpBes6gAFl1/dWQg=="],
|
||||
|
||||
"@jest/environment": ["@jest/environment@29.7.0", "", { "dependencies": { "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "jest-mock": "^29.7.0" } }, "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw=="],
|
||||
|
||||
"@jest/expect": ["@jest/expect@29.7.0", "", { "dependencies": { "expect": "^29.7.0", "jest-snapshot": "^29.7.0" } }, "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ=="],
|
||||
|
||||
"@jest/expect-utils": ["@jest/expect-utils@29.7.0", "", { "dependencies": { "jest-get-type": "^29.6.3" } }, "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA=="],
|
||||
|
||||
"@jest/fake-timers": ["@jest/fake-timers@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", "jest-message-util": "^29.7.0", "jest-mock": "^29.7.0", "jest-util": "^29.7.0" } }, "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ=="],
|
||||
|
||||
"@jest/get-type": ["@jest/get-type@30.5.0", "", {}, "sha512-9/2VUPitAjmBzbvDvqrxmvB7BzWsBW0WmkkojX1ODuxX1NLGxx9gfaZpHB0z8DtJ9uhGNmZG/VXBhf8uO0OV8Q=="],
|
||||
|
||||
"@jest/globals": ["@jest/globals@29.7.0", "", { "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", "@jest/types": "^29.6.3", "jest-mock": "^29.7.0" } }, "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ=="],
|
||||
|
||||
"@jest/react-is-18": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
||||
|
||||
"@jest/react-is-19": ["react-is@19.3.0", "", {}, "sha512-UpMYezM4v5/18F28aC66AEsjXIgE02kyEMH6yLdgLXu/UTfa1Ntwck/nNLrbqJsEXW7gPb0coNO9FQse9WTovA=="],
|
||||
|
||||
"@jest/reporters": ["@jest/reporters@29.7.0", "", { "dependencies": { "@bcoe/v8-coverage": "^0.2.3", "@jest/console": "^29.7.0", "@jest/test-result": "^29.7.0", "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", "jest-message-util": "^29.7.0", "jest-util": "^29.7.0", "jest-worker": "^29.7.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", "v8-to-istanbul": "^9.0.1" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"] }, "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg=="],
|
||||
|
||||
"@jest/schemas": ["@jest/schemas@29.6.3", "", { "dependencies": { "@sinclair/typebox": "^0.27.8" } }, "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA=="],
|
||||
|
||||
"@jest/source-map": ["@jest/source-map@29.6.3", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" } }, "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw=="],
|
||||
|
||||
"@jest/test-result": ["@jest/test-result@29.7.0", "", { "dependencies": { "@jest/console": "^29.7.0", "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA=="],
|
||||
|
||||
"@jest/test-sequencer": ["@jest/test-sequencer@29.7.0", "", { "dependencies": { "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.7.0", "slash": "^3.0.0" } }, "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw=="],
|
||||
|
||||
"@jest/transform": ["@jest/transform@29.7.0", "", { "dependencies": { "@babel/core": "^7.11.6", "@jest/types": "^29.6.3", "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.7.0", "jest-regex-util": "^29.6.3", "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", "write-file-atomic": "^4.0.2" } }, "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw=="],
|
||||
|
||||
"@jest/types": ["@jest/types@29.6.3", "", { "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^17.0.8", "chalk": "^4.0.0" } }, "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw=="],
|
||||
|
|
@ -1084,9 +1050,9 @@
|
|||
|
||||
"@react-native/assets-registry": ["@react-native/assets-registry@0.79.6", "", {}, "sha512-UVSP1224PWg0X+mRlZNftV5xQwZGfawhivuW8fGgxNK9MS/U84xZ+16lkqcPh1ank6MOt239lIWHQ1S33CHgqA=="],
|
||||
|
||||
"@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.79.0-rc.4", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.79.0-rc.4" } }, "sha512-vhYfoFdzz1D/bDAuGThtNia9bUpjtCo73IWfndNoKj+84SOGTtrKaZ/jOpXs5uMskpe1D4xaHuOHHFbzp/0E8g=="],
|
||||
"@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.79.6", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.79.6" } }, "sha512-CS5OrgcMPixOyUJ/Sk/HSsKsKgyKT5P7y3CojimOQzWqRZBmoQfxdST4ugj7n1H+ebM2IKqbgovApFbqXsoX0g=="],
|
||||
|
||||
"@react-native/babel-preset": ["@react-native/babel-preset@0.79.0-rc.4", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.24.7", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-computed-properties": "^7.24.7", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-function-name": "^7.25.1", "@babel/plugin-transform-literals": "^7.25.2", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-numeric-separator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", "@react-native/babel-plugin-codegen": "0.79.0-rc.4", "babel-plugin-syntax-hermes-parser": "0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-0vyO3Ix2N0sI43w0XNJ2zzSWzX7no/JMrXnVzJEm9IhNHsuMmKaXQdRvijDZroepDINIbb6vaIWwzeWkqhiPAA=="],
|
||||
"@react-native/babel-preset": ["@react-native/babel-preset@0.79.6", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.24.7", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-computed-properties": "^7.24.7", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-function-name": "^7.25.1", "@babel/plugin-transform-literals": "^7.25.2", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-numeric-separator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", "@react-native/babel-plugin-codegen": "0.79.6", "babel-plugin-syntax-hermes-parser": "0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-H+FRO+r2Ql6b5IwfE0E7D52JhkxjeGSBSUpCXAI5zQ60zSBJ54Hwh2bBJOohXWl4J+C7gKYSAd2JHMUETu+c/A=="],
|
||||
|
||||
"@react-native/codegen": ["@react-native/codegen@0.79.6", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.25.1", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" } }, "sha512-iRBX8Lgbqypwnfba7s6opeUwVyaR23mowh9ILw7EcT2oLz3RqMmjJdrbVpWhGSMGq2qkPfqAH7bhO8C7O+xfjQ=="],
|
||||
|
||||
|
|
@ -1358,10 +1324,6 @@
|
|||
|
||||
"@tanstack/virtual-file-routes": ["@tanstack/virtual-file-routes@1.161.7", "", { "bin": { "intent": "bin/intent.js" } }, "sha512-olW33+Cn+bsCsZKPwEGhlkqS6w3M2slFv11JIobdnCFKMLG97oAI2kWKdx5/zsywTL8flpnoIgaZZPlQTFYhdQ=="],
|
||||
|
||||
"@testing-library/react-native": ["@testing-library/react-native@13.3.3", "", { "dependencies": { "jest-matcher-utils": "^30.0.5", "picocolors": "^1.1.1", "pretty-format": "^30.0.5", "redent": "^3.0.0" }, "peerDependencies": { "jest": ">=29.0.0", "react": ">=18.2.0", "react-native": ">=0.71", "react-test-renderer": ">=18.2.0" }, "optionalPeers": ["jest"] }, "sha512-k6Mjsd9dbZgvY4Bl7P1NIpePQNi+dfYtlJ5voi9KQlynxSyQkfOgJmYGCYmw/aSgH/rUcFvG8u5gd4npzgRDyg=="],
|
||||
|
||||
"@tootallnate/once": ["@tootallnate/once@2.0.1", "", {}, "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ=="],
|
||||
|
||||
"@trpc/client": ["@trpc/client@11.17.0", "", { "peerDependencies": { "@trpc/server": "11.17.0", "typescript": ">=5.7.2" }, "bin": { "intent": "bin/intent.js" } }, "sha512-KpJBFrbKTDeVCFv/3ckL1XBBH5Yssn8hethI/rUy7GIpTj+VzjtPjykDqJpzobuVOz+d26cXCSu1t4I6MYI5Zg=="],
|
||||
|
||||
"@trpc/react-query": ["@trpc/react-query@11.17.0", "", { "peerDependencies": { "@tanstack/react-query": "^5.80.3", "@trpc/client": "11.17.0", "@trpc/server": "11.17.0", "react": ">=18.2.0", "typescript": ">=5.7.2" } }, "sha512-AGcl5YAF8NnhBmyJ6PqJqKb1M5VTGSoNRNqJ3orct4o4epdcg0GWhW+qT9q6gPzs/2ImIwYCdfFpgNGdZ9yLHA=="],
|
||||
|
|
@ -1424,10 +1386,6 @@
|
|||
|
||||
"@types/istanbul-reports": ["@types/istanbul-reports@3.0.4", "", { "dependencies": { "@types/istanbul-lib-report": "*" } }, "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ=="],
|
||||
|
||||
"@types/jest": ["@types/jest@29.5.14", "", { "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" } }, "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ=="],
|
||||
|
||||
"@types/jsdom": ["@types/jsdom@20.0.1", "", { "dependencies": { "@types/node": "*", "@types/tough-cookie": "*", "parse5": "^7.0.0" } }, "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ=="],
|
||||
|
||||
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
||||
|
||||
"@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
|
||||
|
|
@ -1464,8 +1422,6 @@
|
|||
|
||||
"@types/three": ["@types/three@0.182.0", "", { "dependencies": { "@dimforge/rapier3d-compat": "~0.12.0", "@tweenjs/tween.js": "~23.1.3", "@types/stats.js": "*", "@types/webxr": ">=0.5.17", "@webgpu/types": "*", "fflate": "~0.8.2", "meshoptimizer": "~0.22.0" } }, "sha512-WByN9V3Sbwbe2OkWuSGyoqQO8Du6yhYaXtXLoA5FkKTUJorZ+yOHBZ35zUUPQXlAKABZmbYp5oAqpA4RBjtJ/Q=="],
|
||||
|
||||
"@types/tough-cookie": ["@types/tough-cookie@4.0.5", "", {}, "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="],
|
||||
|
||||
"@types/webxr": ["@types/webxr@0.5.24", "", {}, "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg=="],
|
||||
|
||||
"@types/yargs": ["@types/yargs@17.0.35", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg=="],
|
||||
|
|
@ -1560,16 +1516,12 @@
|
|||
|
||||
"@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="],
|
||||
|
||||
"abab": ["abab@2.0.6", "", {}, "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA=="],
|
||||
|
||||
"abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
|
||||
|
||||
"accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="],
|
||||
|
||||
"acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
|
||||
|
||||
"acorn-globals": ["acorn-globals@7.0.1", "", { "dependencies": { "acorn": "^8.1.0", "acorn-walk": "^8.0.2" } }, "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q=="],
|
||||
|
||||
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
|
||||
|
||||
"acorn-walk": ["acorn-walk@8.3.5", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw=="],
|
||||
|
|
@ -1666,7 +1618,7 @@
|
|||
|
||||
"babel-preset-current-node-syntax": ["babel-preset-current-node-syntax@1.2.0", "", { "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-import-attributes": "^7.24.7", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0 || ^8.0.0-0" } }, "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg=="],
|
||||
|
||||
"babel-preset-expo": ["babel-preset-expo@13.0.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-preset": "0.79.0-rc.4", "babel-plugin-react-native-web": "~0.19.13", "babel-plugin-syntax-hermes-parser": "^0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4", "react-refresh": "^0.14.2", "resolve-from": "^5.0.0" }, "peerDependencies": { "babel-plugin-react-compiler": "^19.0.0-beta-9ee70a1-20241017", "react-compiler-runtime": "^19.0.0-beta-8a03594-20241020" }, "optionalPeers": ["babel-plugin-react-compiler", "react-compiler-runtime"] }, "sha512-4NfamKh+BKu6v0VUtZ2wFuZ9VdaDnYOC+vsAHhUF3ks1jzFLo9TwBqsrkhD129DIHfdhVJnRJah2KRCXEjcrVQ=="],
|
||||
"babel-preset-expo": ["babel-preset-expo@13.2.5", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-preset": "0.79.6", "babel-plugin-react-native-web": "~0.19.13", "babel-plugin-syntax-hermes-parser": "^0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4", "react-refresh": "^0.14.2", "resolve-from": "^5.0.0" }, "peerDependencies": { "babel-plugin-react-compiler": "^19.0.0-beta-e993439-20250405" }, "optionalPeers": ["babel-plugin-react-compiler"] }, "sha512-YjVkP1bOLO2OgR2fyCedruYMPR7GFbAtCvvWITBW1UAp6e3ACYZtN6uoqkXgXP6PHQkb6M7qf2vZreBPEZK38A=="],
|
||||
|
||||
"babel-preset-jest": ["babel-preset-jest@29.6.3", "", { "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA=="],
|
||||
|
||||
|
|
@ -1748,8 +1700,6 @@
|
|||
|
||||
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||
|
||||
"char-regex": ["char-regex@2.0.2", "", {}, "sha512-cbGOjAptfM2LVmWhwRFHEKTPkLwNddVmuqYZQt895yXwAsWsXObCG+YN4DGQ/JBtT4GP1a1lPPdio2z413LmTg=="],
|
||||
|
||||
"character-parser": ["character-parser@2.2.0", "", { "dependencies": { "is-regex": "^1.0.3" } }, "sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw=="],
|
||||
|
||||
"cheerio": ["cheerio@1.2.0", "", { "dependencies": { "cheerio-select": "^2.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "encoding-sniffer": "^0.2.1", "htmlparser2": "^10.1.0", "parse5": "^7.3.0", "parse5-htmlparser2-tree-adapter": "^7.1.0", "parse5-parser-stream": "^7.1.2", "undici": "^7.19.0", "whatwg-mimetype": "^4.0.0" } }, "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg=="],
|
||||
|
|
@ -1766,8 +1716,6 @@
|
|||
|
||||
"ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="],
|
||||
|
||||
"cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="],
|
||||
|
||||
"class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
|
||||
|
||||
"cli-cursor": ["cli-cursor@2.1.0", "", { "dependencies": { "restore-cursor": "^2.0.0" } }, "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw=="],
|
||||
|
|
@ -1782,10 +1730,6 @@
|
|||
|
||||
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
|
||||
|
||||
"co": ["co@4.6.0", "", {}, "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ=="],
|
||||
|
||||
"collect-v8-coverage": ["collect-v8-coverage@1.0.3", "", {}, "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw=="],
|
||||
|
||||
"color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
|
@ -1830,8 +1774,6 @@
|
|||
|
||||
"cosmiconfig": ["cosmiconfig@5.2.1", "", { "dependencies": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" } }, "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA=="],
|
||||
|
||||
"create-jest": ["create-jest@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-config": "^29.7.0", "jest-util": "^29.7.0", "prompts": "^2.0.1" }, "bin": { "create-jest": "bin/create-jest.js" } }, "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q=="],
|
||||
|
||||
"create-require": ["create-require@1.1.1", "", {}, "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="],
|
||||
|
||||
"cross-env": ["cross-env@7.0.3", "", { "dependencies": { "cross-spawn": "^7.0.1" }, "bin": { "cross-env": "src/bin/cross-env.js", "cross-env-shell": "src/bin/cross-env-shell.js" } }, "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw=="],
|
||||
|
|
@ -1854,8 +1796,6 @@
|
|||
|
||||
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
||||
|
||||
"cssom": ["cssom@0.5.0", "", {}, "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw=="],
|
||||
|
||||
"cssstyle": ["cssstyle@6.2.0", "", { "dependencies": { "@asamuzakjp/css-color": "^5.0.1", "@csstools/css-syntax-patches-for-csstree": "^1.0.28", "css-tree": "^3.1.0", "lru-cache": "^11.2.6" } }, "sha512-Fm5NvhYathRnXNVndkUsCCuR63DCLVVwGOOwQw782coXFi5HhkXdu289l59HlXZBawsyNccXfWRYvLzcDCdDig=="],
|
||||
|
||||
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||
|
|
@ -1884,8 +1824,6 @@
|
|||
|
||||
"decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],
|
||||
|
||||
"dedent": ["dedent@1.7.2", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA=="],
|
||||
|
||||
"deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="],
|
||||
|
||||
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
||||
|
|
@ -1912,14 +1850,10 @@
|
|||
|
||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||
|
||||
"detect-newline": ["detect-newline@3.1.0", "", {}, "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA=="],
|
||||
|
||||
"didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="],
|
||||
|
||||
"diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="],
|
||||
|
||||
"diff-sequences": ["diff-sequences@29.6.3", "", {}, "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q=="],
|
||||
|
||||
"dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="],
|
||||
|
||||
"dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="],
|
||||
|
|
@ -1932,8 +1866,6 @@
|
|||
|
||||
"domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
|
||||
|
||||
"domexception": ["domexception@4.0.0", "", { "dependencies": { "webidl-conversions": "^7.0.0" } }, "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw=="],
|
||||
|
||||
"domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="],
|
||||
|
||||
"domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
|
||||
|
|
@ -1960,8 +1892,6 @@
|
|||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.313", "", {}, "sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA=="],
|
||||
|
||||
"emittery": ["emittery@0.13.1", "", {}, "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
|
||||
|
|
@ -2014,8 +1944,6 @@
|
|||
|
||||
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
|
||||
|
||||
"escodegen": ["escodegen@2.1.0", "", { "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", "esutils": "^2.0.2" }, "optionalDependencies": { "source-map": "~0.6.1" }, "bin": { "esgenerate": "bin/esgenerate.js", "escodegen": "bin/escodegen.js" } }, "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w=="],
|
||||
|
||||
"eslint": ["eslint@9.39.4", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.5", "@eslint/js": "9.39.4", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ=="],
|
||||
|
||||
"eslint-config-expo": ["eslint-config-expo@9.2.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "^8.18.2", "@typescript-eslint/parser": "^8.18.2", "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-expo": "^0.1.4", "eslint-plugin-import": "^2.30.0", "eslint-plugin-react": "^7.37.3", "eslint-plugin-react-hooks": "^5.1.0", "globals": "^16.0.0" }, "peerDependencies": { "eslint": ">=8.10" } }, "sha512-TQgmSx+2mRM7qUS0hB5kTDrHcSC35rA1UzOSgK5YRLmSkSMlKLmXkUrhwOpnyo9D/nHdf4ERRAySRYxgA6dlrw=="],
|
||||
|
|
@ -2058,16 +1986,10 @@
|
|||
|
||||
"event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
|
||||
|
||||
"execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="],
|
||||
|
||||
"exit": ["exit@0.1.2", "", {}, "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ=="],
|
||||
|
||||
"exit-hook": ["exit-hook@2.2.1", "", {}, "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw=="],
|
||||
|
||||
"expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="],
|
||||
|
||||
"expect": ["expect@29.7.0", "", { "dependencies": { "@jest/expect-utils": "^29.7.0", "jest-get-type": "^29.6.3", "jest-matcher-utils": "^29.7.0", "jest-message-util": "^29.7.0", "jest-util": "^29.7.0" } }, "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw=="],
|
||||
|
||||
"expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],
|
||||
|
||||
"expo": ["expo@53.0.27", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "0.24.24", "@expo/config": "~11.0.13", "@expo/config-plugins": "~10.1.2", "@expo/fingerprint": "0.13.4", "@expo/metro-config": "0.20.18", "@expo/vector-icons": "^14.0.0", "babel-preset-expo": "~13.2.5", "expo-asset": "~11.1.7", "expo-constants": "~17.1.8", "expo-file-system": "~18.1.11", "expo-font": "~13.3.2", "expo-keep-awake": "~14.1.4", "expo-modules-autolinking": "2.1.15", "expo-modules-core": "2.5.0", "react-native-edge-to-edge": "1.6.0", "whatwg-url-without-unicode": "8.0.0-3" }, "peerDependencies": { "@expo/dom-webview": "*", "@expo/metro-runtime": "*", "react": "*", "react-native": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/dom-webview", "@expo/metro-runtime", "react-native-webview"], "bin": { "expo": "bin/cli", "fingerprint": "bin/fingerprint", "expo-modules-autolinking": "bin/autolinking" } }, "sha512-iQwe2uWLb88opUY4vBYEW1d2GUq3lsa43gsMBEdDV+6pw0Oek93l/4nDLe0ODDdrBRjIJm/rdhKqJC/ehHCUqw=="],
|
||||
|
|
@ -2316,8 +2238,6 @@
|
|||
|
||||
"html-encoding-sniffer": ["html-encoding-sniffer@6.0.0", "", { "dependencies": { "@exodus/bytes": "^1.6.0" } }, "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg=="],
|
||||
|
||||
"html-escaper": ["html-escaper@2.0.2", "", {}, "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="],
|
||||
|
||||
"htmlparser2": ["htmlparser2@10.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "entities": "^7.0.1" } }, "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ=="],
|
||||
|
||||
"http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
|
||||
|
|
@ -2328,8 +2248,6 @@
|
|||
|
||||
"httpxy": ["httpxy@0.5.5", "", {}, "sha512-uDjmnPyp1q4Sgzf3w+J/Fc6UqcCEj0x4Wjp7OqK5dGhNeDgpyrAmnS6ey8QWrX3SWDon2DMKf9sBa5X9+CVyMA=="],
|
||||
|
||||
"human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
|
||||
|
||||
"hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="],
|
||||
|
||||
"iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="],
|
||||
|
|
@ -2344,12 +2262,8 @@
|
|||
|
||||
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
||||
|
||||
"import-local": ["import-local@3.2.0", "", { "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" }, "bin": { "import-local-fixture": "fixtures/cli.js" } }, "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA=="],
|
||||
|
||||
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||
|
||||
"indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="],
|
||||
|
||||
"inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="],
|
||||
|
||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||
|
|
@ -2400,8 +2314,6 @@
|
|||
|
||||
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
||||
|
||||
"is-generator-fn": ["is-generator-fn@2.1.0", "", {}, "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ=="],
|
||||
|
||||
"is-generator-function": ["is-generator-function@1.1.2", "", { "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA=="],
|
||||
|
||||
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
|
||||
|
|
@ -2426,8 +2338,6 @@
|
|||
|
||||
"is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="],
|
||||
|
||||
"is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
|
||||
|
||||
"is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="],
|
||||
|
||||
"is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="],
|
||||
|
|
@ -2454,76 +2364,28 @@
|
|||
|
||||
"istanbul-lib-instrument": ["istanbul-lib-instrument@5.2.1", "", { "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" } }, "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg=="],
|
||||
|
||||
"istanbul-lib-report": ["istanbul-lib-report@3.0.1", "", { "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", "supports-color": "^7.1.0" } }, "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw=="],
|
||||
|
||||
"istanbul-lib-source-maps": ["istanbul-lib-source-maps@4.0.1", "", { "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" } }, "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw=="],
|
||||
|
||||
"istanbul-reports": ["istanbul-reports@3.2.0", "", { "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA=="],
|
||||
|
||||
"iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="],
|
||||
|
||||
"its-fine": ["its-fine@2.0.0", "", { "dependencies": { "@types/react-reconciler": "^0.28.9" }, "peerDependencies": { "react": "^19.0.0" } }, "sha512-KLViCmWx94zOvpLwSlsx6yOCeMhZYaxrJV87Po5k/FoZzcPSahvK5qJ7fYhS61sZi5ikmh2S3Hz55A2l3U69ng=="],
|
||||
|
||||
"jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||
|
||||
"jest": ["jest@29.7.0", "", { "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", "import-local": "^3.0.2", "jest-cli": "^29.7.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"], "bin": { "jest": "bin/jest.js" } }, "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw=="],
|
||||
|
||||
"jest-changed-files": ["jest-changed-files@29.7.0", "", { "dependencies": { "execa": "^5.0.0", "jest-util": "^29.7.0", "p-limit": "^3.1.0" } }, "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w=="],
|
||||
|
||||
"jest-circus": ["jest-circus@29.7.0", "", { "dependencies": { "@jest/environment": "^29.7.0", "@jest/expect": "^29.7.0", "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", "jest-each": "^29.7.0", "jest-matcher-utils": "^29.7.0", "jest-message-util": "^29.7.0", "jest-runtime": "^29.7.0", "jest-snapshot": "^29.7.0", "jest-util": "^29.7.0", "p-limit": "^3.1.0", "pretty-format": "^29.7.0", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw=="],
|
||||
|
||||
"jest-cli": ["jest-cli@29.7.0", "", { "dependencies": { "@jest/core": "^29.7.0", "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", "chalk": "^4.0.0", "create-jest": "^29.7.0", "exit": "^0.1.2", "import-local": "^3.0.2", "jest-config": "^29.7.0", "jest-util": "^29.7.0", "jest-validate": "^29.7.0", "yargs": "^17.3.1" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "optionalPeers": ["node-notifier"], "bin": { "jest": "bin/jest.js" } }, "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg=="],
|
||||
|
||||
"jest-config": ["jest-config@29.7.0", "", { "dependencies": { "@babel/core": "^7.11.6", "@jest/test-sequencer": "^29.7.0", "@jest/types": "^29.6.3", "babel-jest": "^29.7.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "jest-circus": "^29.7.0", "jest-environment-node": "^29.7.0", "jest-get-type": "^29.6.3", "jest-regex-util": "^29.6.3", "jest-resolve": "^29.7.0", "jest-runner": "^29.7.0", "jest-util": "^29.7.0", "jest-validate": "^29.7.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, "peerDependencies": { "@types/node": "*", "ts-node": ">=9.0.0" }, "optionalPeers": ["@types/node", "ts-node"] }, "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ=="],
|
||||
|
||||
"jest-diff": ["jest-diff@30.5.1", "", { "dependencies": { "@jest/diff-sequences": "30.5.0", "@jest/get-type": "30.5.0", "chalk": "^4.1.2", "pretty-format": "30.5.1" } }, "sha512-e3cNNMpv8Kh20MjjphTXs+3Vz7DQyLM1nft7KJhnh46atFhjVJRa+0Hq0beywuwsACtMQUBihQkFl8zxb7gt1Q=="],
|
||||
|
||||
"jest-docblock": ["jest-docblock@29.7.0", "", { "dependencies": { "detect-newline": "^3.0.0" } }, "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g=="],
|
||||
|
||||
"jest-each": ["jest-each@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", "jest-get-type": "^29.6.3", "jest-util": "^29.7.0", "pretty-format": "^29.7.0" } }, "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ=="],
|
||||
|
||||
"jest-environment-jsdom": ["jest-environment-jsdom@29.7.0", "", { "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/jsdom": "^20.0.0", "@types/node": "*", "jest-mock": "^29.7.0", "jest-util": "^29.7.0", "jsdom": "^20.0.0" }, "peerDependencies": { "canvas": "^2.5.0" }, "optionalPeers": ["canvas"] }, "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA=="],
|
||||
|
||||
"jest-environment-node": ["jest-environment-node@29.7.0", "", { "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "jest-mock": "^29.7.0", "jest-util": "^29.7.0" } }, "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw=="],
|
||||
|
||||
"jest-expo": ["jest-expo@53.0.14", "", { "dependencies": { "@expo/config": "~11.0.13", "@expo/json-file": "^9.1.5", "@jest/create-cache-key-function": "^29.2.1", "@jest/globals": "^29.2.1", "babel-jest": "^29.2.1", "find-up": "^5.0.0", "jest-environment-jsdom": "^29.2.1", "jest-snapshot": "^29.2.1", "jest-watch-select-projects": "^2.0.0", "jest-watch-typeahead": "2.2.1", "json5": "^2.2.3", "lodash": "^4.17.19", "react-test-renderer": "19.0.0", "server-only": "^0.0.1", "stacktrace-js": "^2.0.2" }, "peerDependencies": { "expo": "*", "react-native": "*", "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" }, "optionalPeers": ["react-server-dom-webpack"], "bin": { "jest": "bin/jest.js" } }, "sha512-BwE5ZTjkhTvO+ejJBBJNlwar2YiahWjbcwhSPQ3oYV5UyvVdTrpKvZ+KjFv/7N5OaC3cOhv4/Ve4cTgS6m6vcw=="],
|
||||
|
||||
"jest-get-type": ["jest-get-type@29.6.3", "", {}, "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw=="],
|
||||
|
||||
"jest-haste-map": ["jest-haste-map@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.6.3", "jest-util": "^29.7.0", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA=="],
|
||||
|
||||
"jest-leak-detector": ["jest-leak-detector@29.7.0", "", { "dependencies": { "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" } }, "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw=="],
|
||||
|
||||
"jest-matcher-utils": ["jest-matcher-utils@30.5.1", "", { "dependencies": { "@jest/get-type": "30.5.0", "chalk": "^4.1.2", "jest-diff": "30.5.1", "pretty-format": "30.5.1" } }, "sha512-aroZVqwOz/wC2y6pC+obgFWKV9viaQWQTTSB6W5H55+egtUczIfXR/rxExTv92xD/ADYwpqaYfVWx1aqwKg7FA=="],
|
||||
|
||||
"jest-message-util": ["jest-message-util@29.7.0", "", { "dependencies": { "@babel/code-frame": "^7.12.13", "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w=="],
|
||||
|
||||
"jest-mock": ["jest-mock@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", "jest-util": "^29.7.0" } }, "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw=="],
|
||||
|
||||
"jest-pnp-resolver": ["jest-pnp-resolver@1.2.3", "", { "peerDependencies": { "jest-resolve": "*" }, "optionalPeers": ["jest-resolve"] }, "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w=="],
|
||||
|
||||
"jest-regex-util": ["jest-regex-util@29.6.3", "", {}, "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg=="],
|
||||
|
||||
"jest-resolve": ["jest-resolve@29.7.0", "", { "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.7.0", "jest-pnp-resolver": "^1.2.2", "jest-util": "^29.7.0", "jest-validate": "^29.7.0", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" } }, "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA=="],
|
||||
|
||||
"jest-resolve-dependencies": ["jest-resolve-dependencies@29.7.0", "", { "dependencies": { "jest-regex-util": "^29.6.3", "jest-snapshot": "^29.7.0" } }, "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA=="],
|
||||
|
||||
"jest-runner": ["jest-runner@29.7.0", "", { "dependencies": { "@jest/console": "^29.7.0", "@jest/environment": "^29.7.0", "@jest/test-result": "^29.7.0", "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.7.0", "jest-environment-node": "^29.7.0", "jest-haste-map": "^29.7.0", "jest-leak-detector": "^29.7.0", "jest-message-util": "^29.7.0", "jest-resolve": "^29.7.0", "jest-runtime": "^29.7.0", "jest-util": "^29.7.0", "jest-watcher": "^29.7.0", "jest-worker": "^29.7.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" } }, "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ=="],
|
||||
|
||||
"jest-runtime": ["jest-runtime@29.7.0", "", { "dependencies": { "@jest/environment": "^29.7.0", "@jest/fake-timers": "^29.7.0", "@jest/globals": "^29.7.0", "@jest/source-map": "^29.6.3", "@jest/test-result": "^29.7.0", "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", "jest-haste-map": "^29.7.0", "jest-message-util": "^29.7.0", "jest-mock": "^29.7.0", "jest-regex-util": "^29.6.3", "jest-resolve": "^29.7.0", "jest-snapshot": "^29.7.0", "jest-util": "^29.7.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" } }, "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ=="],
|
||||
|
||||
"jest-snapshot": ["jest-snapshot@29.7.0", "", { "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/types": "^7.3.3", "@jest/expect-utils": "^29.7.0", "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", "expect": "^29.7.0", "graceful-fs": "^4.2.9", "jest-diff": "^29.7.0", "jest-get-type": "^29.6.3", "jest-matcher-utils": "^29.7.0", "jest-message-util": "^29.7.0", "jest-util": "^29.7.0", "natural-compare": "^1.4.0", "pretty-format": "^29.7.0", "semver": "^7.5.3" } }, "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw=="],
|
||||
|
||||
"jest-util": ["jest-util@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" } }, "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA=="],
|
||||
|
||||
"jest-validate": ["jest-validate@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.6.3", "leven": "^3.1.0", "pretty-format": "^29.7.0" } }, "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw=="],
|
||||
|
||||
"jest-watch-select-projects": ["jest-watch-select-projects@2.0.0", "", { "dependencies": { "ansi-escapes": "^4.3.0", "chalk": "^3.0.0", "prompts": "^2.2.1" } }, "sha512-j00nW4dXc2NiCW6znXgFLF9g8PJ0zP25cpQ1xRro/HU2GBfZQFZD0SoXnAlaoKkIY4MlfTMkKGbNXFpvCdjl1w=="],
|
||||
|
||||
"jest-watch-typeahead": ["jest-watch-typeahead@2.2.1", "", { "dependencies": { "ansi-escapes": "^6.0.0", "chalk": "^4.0.0", "jest-regex-util": "^29.0.0", "jest-watcher": "^29.0.0", "slash": "^5.0.0", "string-length": "^5.0.1", "strip-ansi": "^7.0.1" }, "peerDependencies": { "jest": "^27.0.0 || ^28.0.0 || ^29.0.0" } }, "sha512-jYpYmUnTzysmVnwq49TAxlmtOAwp8QIqvZyoofQFn8fiWhEDZj33ZXzg3JA4nGnzWFm1hbWf3ADpteUokvXgFA=="],
|
||||
|
||||
"jest-watcher": ["jest-watcher@29.7.0", "", { "dependencies": { "@jest/test-result": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", "jest-util": "^29.7.0", "string-length": "^4.0.1" } }, "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g=="],
|
||||
|
||||
"jest-worker": ["jest-worker@29.7.0", "", { "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw=="],
|
||||
|
||||
"jimp-compact": ["jimp-compact@0.16.1", "", {}, "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww=="],
|
||||
|
|
@ -2548,8 +2410,6 @@
|
|||
|
||||
"json-parse-better-errors": ["json-parse-better-errors@1.0.2", "", {}, "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="],
|
||||
|
||||
"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@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
|
||||
|
||||
"json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
|
||||
|
|
@ -2636,8 +2496,6 @@
|
|||
|
||||
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||
|
||||
"make-dir": ["make-dir@4.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw=="],
|
||||
|
||||
"make-error": ["make-error@1.3.6", "", {}, "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="],
|
||||
|
||||
"makeerror": ["makeerror@1.0.12", "", { "dependencies": { "tmpl": "1.0.5" } }, "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg=="],
|
||||
|
|
@ -2702,12 +2560,10 @@
|
|||
|
||||
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||
|
||||
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
||||
"mimic-fn": ["mimic-fn@1.2.0", "", {}, "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="],
|
||||
|
||||
"mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
|
||||
|
||||
"min-indent": ["min-indent@1.0.1", "", {}, "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="],
|
||||
|
||||
"miniflare": ["miniflare@4.20260616.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "0.34.5", "undici": "7.24.8", "workerd": "1.20260616.1", "ws": "8.20.1", "youch": "4.1.0-beta.10" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-cEpzoNgSWjedzYmhJvttUPmL4Jk6nSzzeNNi118T5zwnmYP9fnM8UXwFU/Qa/1qoQ4SzGqtM1Q7tinHvHvIGtw=="],
|
||||
|
||||
"minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
||||
|
|
@ -2766,14 +2622,10 @@
|
|||
|
||||
"npm-package-arg": ["npm-package-arg@11.0.3", "", { "dependencies": { "hosted-git-info": "^7.0.0", "proc-log": "^4.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^5.0.0" } }, "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw=="],
|
||||
|
||||
"npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="],
|
||||
|
||||
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
|
||||
|
||||
"nullthrows": ["nullthrows@1.1.1", "", {}, "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw=="],
|
||||
|
||||
"nwsapi": ["nwsapi@2.2.27", "", {}, "sha512-gQPNF78qebCQ6tvVFBYrvJdBNOrYZm90ZlXgpIFm06p6qHDHq/XC4TnJftN6OMbxVE0UTBAoRgcsDeJBBooITw=="],
|
||||
|
||||
"ob1": ["ob1@0.82.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-QyQQ6e66f+Ut/qUVjEce0E/wux5nAGLXYZDn1jr15JWstHsCH3l6VVrg8NKDptW9NEiBXKOJeGF/ydxeSDF3IQ=="],
|
||||
|
||||
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||
|
|
@ -2810,7 +2662,7 @@
|
|||
|
||||
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
|
||||
|
||||
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
|
||||
"onetime": ["onetime@2.0.1", "", { "dependencies": { "mimic-fn": "^1.0.0" } }, "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ=="],
|
||||
|
||||
"open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="],
|
||||
|
||||
|
|
@ -2830,7 +2682,7 @@
|
|||
|
||||
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
|
||||
|
||||
"parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="],
|
||||
"parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="],
|
||||
|
||||
"parse-png": ["parse-png@2.1.0", "", { "dependencies": { "pngjs": "^3.3.0" } }, "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ=="],
|
||||
|
||||
|
|
@ -2884,8 +2736,6 @@
|
|||
|
||||
"pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="],
|
||||
|
||||
"pkg-dir": ["pkg-dir@4.2.0", "", { "dependencies": { "find-up": "^4.0.0" } }, "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ=="],
|
||||
|
||||
"playwright": ["playwright@1.63.0", "", { "dependencies": { "playwright-core": "1.63.0" }, "bin": { "playwright": "cli.js" } }, "sha512-+7ziBLidS4NaNCdt57SUDT+wYmmd5fmiQejUic/kb+YsYSCPyOOE9sebzMjNmQrsnNpDJqd4WHvV/8lfKfUDUg=="],
|
||||
|
||||
"playwright-core": ["playwright-core@1.63.0", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-rYCsBF/M5HjUch52bbtVONEFjv6Xu8sm8h72dNlR5bzIE1fvC/bxgspzkjSfU+MweEMmPM8KJebG6nnyxo5mCg=="],
|
||||
|
|
@ -2960,8 +2810,6 @@
|
|||
|
||||
"proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="],
|
||||
|
||||
"psl": ["psl@1.15.0", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w=="],
|
||||
|
||||
"pug": ["pug@3.0.4", "", { "dependencies": { "pug-code-gen": "^3.0.4", "pug-filters": "^4.0.0", "pug-lexer": "^5.0.1", "pug-linker": "^4.0.0", "pug-load": "^3.0.0", "pug-parser": "^6.0.0", "pug-runtime": "^3.0.1", "pug-strip-comments": "^2.0.0" } }, "sha512-kFfq5mMzrS7+wrl5pLJzZEzemx34OQ0w4SARfhy/3yxTlhbstsudDwJzhf1hP02yHzbjoVMSXUj/Sz6RNfMyXg=="],
|
||||
|
||||
"pug-attrs": ["pug-attrs@3.0.0", "", { "dependencies": { "constantinople": "^4.0.1", "js-stringify": "^1.0.2", "pug-runtime": "^3.0.0" } }, "sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA=="],
|
||||
|
|
@ -2990,16 +2838,12 @@
|
|||
|
||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||
|
||||
"pure-rand": ["pure-rand@6.1.0", "", {}, "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA=="],
|
||||
|
||||
"qrcode-terminal": ["qrcode-terminal@0.11.0", "", { "bin": { "qrcode-terminal": "./bin/qrcode-terminal.js" } }, "sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ=="],
|
||||
|
||||
"qs": ["qs@6.14.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q=="],
|
||||
|
||||
"query-string": ["query-string@7.1.3", "", { "dependencies": { "decode-uri-component": "^0.2.2", "filter-obj": "^1.1.0", "split-on-first": "^1.0.0", "strict-uri-encode": "^2.0.0" } }, "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg=="],
|
||||
|
||||
"querystringify": ["querystringify@2.2.0", "", {}, "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ=="],
|
||||
|
||||
"queue": ["queue@6.0.2", "", { "dependencies": { "inherits": "~2.0.3" } }, "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA=="],
|
||||
|
||||
"queue-lit": ["queue-lit@1.5.2", "", {}, "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw=="],
|
||||
|
|
@ -3026,7 +2870,7 @@
|
|||
|
||||
"react-hook-form": ["react-hook-form@7.71.2", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-1CHvcDYzuRUNOflt4MOq3ZM46AronNJtQ1S7tnX6YN4y72qhgiUItpacZUAQ0TyWYci3yz1X+rXaSxiuEm86PA=="],
|
||||
|
||||
"react-is": ["react-is@19.2.4", "", {}, "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA=="],
|
||||
"react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
||||
|
||||
"react-native": ["react-native@0.79.6", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.79.6", "@react-native/codegen": "0.79.6", "@react-native/community-cli-plugin": "0.79.6", "@react-native/gradle-plugin": "0.79.6", "@react-native/js-polyfills": "0.79.6", "@react-native/normalize-colors": "0.79.6", "@react-native/virtualized-lists": "0.79.6", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", "babel-plugin-syntax-hermes-parser": "0.25.1", "base64-js": "^1.5.1", "chalk": "^4.0.0", "commander": "^12.0.0", "event-target-shim": "^5.0.1", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.82.0", "metro-source-map": "^0.82.0", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.1.1", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.25.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^6.2.3", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.0.0", "react": "^19.0.0" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-kvIWSmf4QPfY41HC25TR285N7Fv0Pyn3DAEK8qRL9dA35usSaxsJkHfw+VqnonqJjXOaoKCEanwudRAJ60TBGA=="],
|
||||
|
||||
|
|
@ -3072,8 +2916,6 @@
|
|||
|
||||
"react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="],
|
||||
|
||||
"react-test-renderer": ["react-test-renderer@19.0.0", "", { "dependencies": { "react-is": "^19.0.0", "scheduler": "^0.25.0" }, "peerDependencies": { "react": "^19.0.0" } }, "sha512-oX5u9rOQlHzqrE/64CNr0HB0uWxkCQmZNSfozlYvwE71TLVgeZxVf0IjouGEr1v7r1kcDifdAJBeOhdhxsG/DA=="],
|
||||
|
||||
"react-use-measure": ["react-use-measure@2.1.7", "", { "peerDependencies": { "react": ">=16.13", "react-dom": ">=16.13" }, "optionalPeers": ["react-dom"] }, "sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg=="],
|
||||
|
||||
"read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="],
|
||||
|
|
@ -3082,8 +2924,6 @@
|
|||
|
||||
"readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
|
||||
|
||||
"redent": ["redent@3.0.0", "", { "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" } }, "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg=="],
|
||||
|
||||
"reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="],
|
||||
|
||||
"regenerate": ["regenerate@1.4.2", "", {}, "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="],
|
||||
|
|
@ -3106,12 +2946,8 @@
|
|||
|
||||
"requireg": ["requireg@0.2.2", "", { "dependencies": { "nested-error-stacks": "~2.0.1", "rc": "~1.2.7", "resolve": "~1.7.1" } }, "sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg=="],
|
||||
|
||||
"requires-port": ["requires-port@1.0.0", "", {}, "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="],
|
||||
|
||||
"resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="],
|
||||
|
||||
"resolve-cwd": ["resolve-cwd@3.0.0", "", { "dependencies": { "resolve-from": "^5.0.0" } }, "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg=="],
|
||||
|
||||
"resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
|
||||
|
||||
"resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
|
||||
|
|
@ -3248,18 +3084,12 @@
|
|||
|
||||
"stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="],
|
||||
|
||||
"stack-generator": ["stack-generator@2.0.10", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ=="],
|
||||
|
||||
"stack-utils": ["stack-utils@2.0.6", "", { "dependencies": { "escape-string-regexp": "^2.0.0" } }, "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ=="],
|
||||
|
||||
"stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
|
||||
|
||||
"stackframe": ["stackframe@1.3.4", "", {}, "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="],
|
||||
|
||||
"stacktrace-gps": ["stacktrace-gps@3.1.2", "", { "dependencies": { "source-map": "0.5.6", "stackframe": "^1.3.4" } }, "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ=="],
|
||||
|
||||
"stacktrace-js": ["stacktrace-js@2.0.2", "", { "dependencies": { "error-stack-parser": "^2.0.6", "stack-generator": "^2.0.5", "stacktrace-gps": "^3.0.4" } }, "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg=="],
|
||||
|
||||
"stacktrace-parser": ["stacktrace-parser@0.1.11", "", { "dependencies": { "type-fest": "^0.7.1" } }, "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg=="],
|
||||
|
||||
"stacktracey": ["stacktracey@2.2.0", "", { "dependencies": { "as-table": "^1.0.36", "get-source": "^2.0.12" } }, "sha512-ETyQEz+CzXiLjEbyJqpbp+/T79RQD/6wqFucRBIlVNZfYq2Ay7wbretD4cxpbymZlaPWx58aIhPEY1Cr8DlVvg=="],
|
||||
|
|
@ -3280,8 +3110,6 @@
|
|||
|
||||
"strict-uri-encode": ["strict-uri-encode@2.0.0", "", {}, "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="],
|
||||
|
||||
"string-length": ["string-length@5.0.1", "", { "dependencies": { "char-regex": "^2.0.0", "strip-ansi": "^7.0.1" } }, "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow=="],
|
||||
|
||||
"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=="],
|
||||
|
||||
"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=="],
|
||||
|
|
@ -3298,16 +3126,12 @@
|
|||
|
||||
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
||||
|
||||
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
"strip-ansi": ["strip-ansi@5.2.0", "", { "dependencies": { "ansi-regex": "^4.1.0" } }, "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA=="],
|
||||
|
||||
"strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
|
||||
|
||||
"strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
|
||||
|
||||
"strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="],
|
||||
|
||||
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
|
||||
|
||||
"structured-headers": ["structured-headers@0.4.1", "", {}, "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg=="],
|
||||
|
|
@ -3486,8 +3310,6 @@
|
|||
|
||||
"unique-string": ["unique-string@2.0.0", "", { "dependencies": { "crypto-random-string": "^2.0.0" } }, "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg=="],
|
||||
|
||||
"universalify": ["universalify@0.2.0", "", {}, "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg=="],
|
||||
|
||||
"unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
|
||||
|
||||
"unplugin": ["unplugin@3.0.0", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-0Mqk3AT2TZCXWKdcoaufeXNukv2mTrEZExeXlHIOZXdqYoHHr4n51pymnwV8x2BOVxwXbK2HLlI7usrqMpycdg=="],
|
||||
|
|
@ -3500,8 +3322,6 @@
|
|||
|
||||
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
||||
|
||||
"url-parse": ["url-parse@1.5.10", "", { "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ=="],
|
||||
|
||||
"use-latest-callback": ["use-latest-callback@0.2.6", "", { "peerDependencies": { "react": ">=16.8" } }, "sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg=="],
|
||||
|
||||
"use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
|
||||
|
|
@ -3520,8 +3340,6 @@
|
|||
|
||||
"v8-compile-cache-lib": ["v8-compile-cache-lib@3.0.1", "", {}, "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="],
|
||||
|
||||
"v8-to-istanbul": ["v8-to-istanbul@9.3.0", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^2.0.0" } }, "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA=="],
|
||||
|
||||
"validate-npm-package-name": ["validate-npm-package-name@5.0.1", "", {}, "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ=="],
|
||||
|
||||
"vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
|
||||
|
|
@ -3558,7 +3376,7 @@
|
|||
|
||||
"webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="],
|
||||
|
||||
"whatwg-encoding": ["whatwg-encoding@2.0.0", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg=="],
|
||||
"whatwg-encoding": ["whatwg-encoding@3.1.1", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ=="],
|
||||
|
||||
"whatwg-fetch": ["whatwg-fetch@3.6.20", "", {}, "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="],
|
||||
|
||||
|
|
@ -3728,20 +3546,10 @@
|
|||
|
||||
"@istanbuljs/load-nyc-config/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=="],
|
||||
|
||||
"@jest/console/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"@jest/core/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"@jest/environment/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"@jest/fake-timers/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"@jest/reporters/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"@jest/reporters/istanbul-lib-instrument": ["istanbul-lib-instrument@6.0.3", "", { "dependencies": { "@babel/core": "^7.23.9", "@babel/parser": "^7.23.9", "@istanbuljs/schema": "^0.1.3", "istanbul-lib-coverage": "^3.2.0", "semver": "^7.5.4" } }, "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q=="],
|
||||
|
||||
"@jest/reporters/string-length": ["string-length@4.0.2", "", { "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" } }, "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ=="],
|
||||
|
||||
"@jest/types/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"@maplibre/maplibre-gl-style-spec/quickselect": ["quickselect@2.0.0", "", {}, "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="],
|
||||
|
|
@ -3768,14 +3576,14 @@
|
|||
|
||||
"@poppinss/dumper/supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="],
|
||||
|
||||
"@react-native/babel-plugin-codegen/@react-native/codegen": ["@react-native/codegen@0.79.0-rc.4", "", { "dependencies": { "glob": "^7.1.1", "hermes-parser": "0.25.1", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" }, "peerDependencies": { "@babel/core": "*" } }, "sha512-62J5LVV0LBqyqSV1REin2+ciWamctlYMFyy216Gko/+aqMdoYVX/bM14pdPmqtPZRoMEgWQCgmfw+xc0yx9aPQ=="],
|
||||
|
||||
"@react-native/community-cli-plugin/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||
|
||||
"@react-native/community-cli-plugin/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||
|
||||
"@react-native/dev-middleware/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
|
||||
|
||||
"@react-navigation/core/react-is": ["react-is@19.2.4", "", {}, "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA=="],
|
||||
|
||||
"@tailwindcss/node/jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="],
|
||||
|
|
@ -3812,16 +3620,10 @@
|
|||
|
||||
"@tanstack/start-plugin-core/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
||||
|
||||
"@testing-library/react-native/pretty-format": ["pretty-format@30.5.1", "", { "dependencies": { "@jest/react-is-18": "npm:react-is@^18.3.1", "@jest/react-is-19": "npm:react-is@^19.2.5", "@jest/schemas": "30.5.0", "ansi-styles": "^5.2.0" } }, "sha512-byhRAPguVKMQIj4kjJwJ5lAskVhfuiSdiYl/aLTWpgkGEmic2jYhJh1yE9ih8Ox44Xg9ccCT11/S6QrzSJuNrg=="],
|
||||
|
||||
"@types/better-sqlite3/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"@types/graceful-fs/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"@types/jsdom/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"@types/jsdom/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
|
||||
|
||||
"@types/pg/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||
|
|
@ -3888,6 +3690,8 @@
|
|||
|
||||
"chromium-edge-launcher/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
|
||||
|
||||
"cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"common-ui/react-native-pager-view": ["react-native-pager-view@6.9.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-uUT0MMMbNtoSbxe9pRvdJJKEi9snjuJ3fXlZhG8F2vVMOBJVt/AFtqMPUHu9yMflmqOr08PewKzj9EPl/Yj+Gw=="],
|
||||
|
||||
"common-ui/zustand": ["zustand@5.0.13", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-efI2tVaVQPqtOh114loML/Z80Y4NP3yc+Ff0fYiZJPauNeWZeIp/bRFD7I9bfmCOYBh/PHxlglQ9+wvlwnPikQ=="],
|
||||
|
|
@ -3906,8 +3710,6 @@
|
|||
|
||||
"cosmiconfig/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=="],
|
||||
|
||||
"cosmiconfig/parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="],
|
||||
|
||||
"css-tree/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"cssstyle/css-tree": ["css-tree@3.2.1", "", { "dependencies": { "mdn-data": "2.27.1", "source-map-js": "^1.2.1" } }, "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA=="],
|
||||
|
|
@ -3916,20 +3718,14 @@
|
|||
|
||||
"dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
||||
|
||||
"domexception/webidl-conversions": ["webidl-conversions@7.0.0", "", {}, "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="],
|
||||
|
||||
"dotenv-expand/dotenv": ["dotenv@16.4.7", "", {}, "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ=="],
|
||||
|
||||
"encoding-sniffer/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
|
||||
|
||||
"encoding-sniffer/whatwg-encoding": ["whatwg-encoding@3.1.1", "", { "dependencies": { "iconv-lite": "0.6.3" } }, "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ=="],
|
||||
|
||||
"env-runner/exsolve": ["exsolve@1.1.1", "", {}, "sha512-9U/jZUgjnSGyntRr6y5Muu1MJcwFl6kPu7k8qLF0IMNfLqvw0NZ4nnVDq0RVoZ0RvCyumib4Ez3KYrVfilrw+g=="],
|
||||
|
||||
"error-ex/is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="],
|
||||
|
||||
"escodegen/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
||||
|
||||
"eslint-import-resolver-typescript/tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||
|
|
@ -3940,12 +3736,6 @@
|
|||
|
||||
"eslint-plugin-react/resolve": ["resolve@2.0.0-next.6", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA=="],
|
||||
|
||||
"execa/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
||||
|
||||
"expect/jest-matcher-utils": ["jest-matcher-utils@29.7.0", "", { "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.7.0", "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" } }, "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g=="],
|
||||
|
||||
"expo/babel-preset-expo": ["babel-preset-expo@13.2.5", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-preset": "0.79.6", "babel-plugin-react-native-web": "~0.19.13", "babel-plugin-syntax-hermes-parser": "^0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4", "react-refresh": "^0.14.2", "resolve-from": "^5.0.0" }, "peerDependencies": { "babel-plugin-react-compiler": "^19.0.0-beta-e993439-20250405" }, "optionalPeers": ["babel-plugin-react-compiler"] }, "sha512-YjVkP1bOLO2OgR2fyCedruYMPR7GFbAtCvvWITBW1UAp6e3ACYZtN6uoqkXgXP6PHQkb6M7qf2vZreBPEZK38A=="],
|
||||
|
||||
"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-modules-autolinking/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
|
||||
|
|
@ -4006,58 +3796,16 @@
|
|||
|
||||
"is-expression/acorn": ["acorn@7.4.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A=="],
|
||||
|
||||
"istanbul-lib-source-maps/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"jest-circus/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"jest-circus/jest-matcher-utils": ["jest-matcher-utils@29.7.0", "", { "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.7.0", "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" } }, "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g=="],
|
||||
|
||||
"jest-config/deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
|
||||
|
||||
"jest-diff/pretty-format": ["pretty-format@30.5.1", "", { "dependencies": { "@jest/react-is-18": "npm:react-is@^18.3.1", "@jest/react-is-19": "npm:react-is@^19.2.5", "@jest/schemas": "30.5.0", "ansi-styles": "^5.2.0" } }, "sha512-byhRAPguVKMQIj4kjJwJ5lAskVhfuiSdiYl/aLTWpgkGEmic2jYhJh1yE9ih8Ox44Xg9ccCT11/S6QrzSJuNrg=="],
|
||||
|
||||
"jest-environment-jsdom/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom": ["jsdom@20.0.3", "", { "dependencies": { "abab": "^2.0.6", "acorn": "^8.8.1", "acorn-globals": "^7.0.0", "cssom": "^0.5.0", "cssstyle": "^2.3.0", "data-urls": "^3.0.2", "decimal.js": "^10.4.2", "domexception": "^4.0.0", "escodegen": "^2.0.0", "form-data": "^4.0.0", "html-encoding-sniffer": "^3.0.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.1", "is-potential-custom-element-name": "^1.0.1", "nwsapi": "^2.2.2", "parse5": "^7.1.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^4.1.2", "w3c-xmlserializer": "^4.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^2.0.0", "whatwg-mimetype": "^3.0.0", "whatwg-url": "^11.0.0", "ws": "^8.11.0", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "canvas": "^2.5.0" }, "optionalPeers": ["canvas"] }, "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ=="],
|
||||
|
||||
"jest-environment-node/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"jest-haste-map/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"jest-matcher-utils/pretty-format": ["pretty-format@30.5.1", "", { "dependencies": { "@jest/react-is-18": "npm:react-is@^18.3.1", "@jest/react-is-19": "npm:react-is@^19.2.5", "@jest/schemas": "30.5.0", "ansi-styles": "^5.2.0" } }, "sha512-byhRAPguVKMQIj4kjJwJ5lAskVhfuiSdiYl/aLTWpgkGEmic2jYhJh1yE9ih8Ox44Xg9ccCT11/S6QrzSJuNrg=="],
|
||||
|
||||
"jest-mock/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"jest-runner/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"jest-runner/source-map-support": ["source-map-support@0.5.13", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w=="],
|
||||
|
||||
"jest-runtime/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"jest-runtime/strip-bom": ["strip-bom@4.0.0", "", {}, "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w=="],
|
||||
|
||||
"jest-snapshot/jest-diff": ["jest-diff@29.7.0", "", { "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" } }, "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw=="],
|
||||
|
||||
"jest-snapshot/jest-matcher-utils": ["jest-matcher-utils@29.7.0", "", { "dependencies": { "chalk": "^4.0.0", "jest-diff": "^29.7.0", "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" } }, "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g=="],
|
||||
|
||||
"jest-snapshot/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||
|
||||
"jest-util/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"jest-util/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"jest-watch-select-projects/chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="],
|
||||
|
||||
"jest-watch-typeahead/ansi-escapes": ["ansi-escapes@6.2.1", "", {}, "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig=="],
|
||||
|
||||
"jest-watch-typeahead/slash": ["slash@5.1.0", "", {}, "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="],
|
||||
|
||||
"jest-watch-typeahead/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
|
||||
|
||||
"jest-watcher/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"jest-watcher/string-length": ["string-length@4.0.2", "", { "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" } }, "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ=="],
|
||||
|
||||
"jest-worker/@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
||||
|
||||
"jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
|
||||
|
|
@ -4070,8 +3818,6 @@
|
|||
|
||||
"log-symbols/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=="],
|
||||
|
||||
"make-dir/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||
|
||||
"metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="],
|
||||
|
||||
"metro/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
||||
|
|
@ -4098,22 +3844,16 @@
|
|||
|
||||
"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=="],
|
||||
|
||||
"ora/strip-ansi": ["strip-ansi@5.2.0", "", { "dependencies": { "ansi-regex": "^4.1.0" } }, "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA=="],
|
||||
|
||||
"parse5-htmlparser2-tree-adapter/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
|
||||
|
||||
"parse5-parser-stream/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
|
||||
|
||||
"path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
"pkg-dir/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],
|
||||
|
||||
"plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="],
|
||||
|
||||
"pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
|
||||
|
||||
"pretty-format/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
||||
|
||||
"prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
|
||||
|
||||
"rc/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
|
||||
|
|
@ -4138,14 +3878,10 @@
|
|||
|
||||
"react-native-web/memoize-one": ["memoize-one@6.0.0", "", {}, "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="],
|
||||
|
||||
"react-test-renderer/scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="],
|
||||
|
||||
"readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"requireg/resolve": ["resolve@1.7.1", "", { "dependencies": { "path-parse": "^1.0.5" } }, "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw=="],
|
||||
|
||||
"restore-cursor/onetime": ["onetime@2.0.1", "", { "dependencies": { "mimic-fn": "^1.0.0" } }, "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ=="],
|
||||
|
||||
"restore-cursor/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
||||
|
||||
"rimraf/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
|
||||
|
|
@ -4168,13 +3904,15 @@
|
|||
|
||||
"stack-utils/escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="],
|
||||
|
||||
"stacktrace-gps/source-map": ["source-map@0.5.6", "", {}, "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA=="],
|
||||
|
||||
"stacktrace-parser/type-fest": ["type-fest@0.7.1", "", {}, "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg=="],
|
||||
|
||||
"stats-gl/three": ["three@0.170.0", "", {}, "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ=="],
|
||||
|
||||
"string-length/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
|
||||
"string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
|
||||
|
||||
"sucrase/commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
|
||||
|
||||
|
|
@ -4246,6 +3984,10 @@
|
|||
|
||||
"wrangler/esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="],
|
||||
|
||||
"wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"write-file-atomic/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
||||
|
||||
"youch/cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
|
||||
|
|
@ -4346,20 +4088,10 @@
|
|||
|
||||
"@istanbuljs/load-nyc-config/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
|
||||
|
||||
"@jest/console/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@jest/core/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@jest/environment/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@jest/fake-timers/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@jest/reporters/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@jest/reporters/istanbul-lib-instrument/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||
|
||||
"@jest/reporters/string-length/char-regex": ["char-regex@1.0.2", "", {}, "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="],
|
||||
|
||||
"@jest/types/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@packages/db_helper_postgres/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
|
@ -4374,18 +4106,10 @@
|
|||
|
||||
"@tanstack/router-devtools/@tanstack/react-router-devtools/@tanstack/router-devtools-core": ["@tanstack/router-devtools-core@1.166.9", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16", "tiny-invariant": "^1.3.3" }, "peerDependencies": { "@tanstack/router-core": "^1.167.2", "csstype": "^3.0.10" }, "optionalPeers": ["csstype"] }, "sha512-PNlA7GmOUX9wY7LUG709Pk3Lg33dfHBztQwzjzrOiOsuf4ggp2R6bwarF8nYGNjG79z/MaB5PN+5yvkCVk8jGw=="],
|
||||
|
||||
"@testing-library/react-native/pretty-format/@jest/schemas": ["@jest/schemas@30.5.0", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-/hunigyNpc4RCjC0VaW3f5RCUZVM2+WQ65qP7z083Gmvac7or2LI50XVNOtE4YPgBpV0yxYiAgorAPGniCoJmg=="],
|
||||
|
||||
"@testing-library/react-native/pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
|
||||
|
||||
"@types/better-sqlite3/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/graceful-fs/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/jsdom/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@types/jsdom/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
|
||||
|
||||
"@types/pg/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="],
|
||||
|
|
@ -4442,16 +4166,12 @@
|
|||
|
||||
"eslint-import-resolver-typescript/tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||
|
||||
"expect/jest-matcher-utils/jest-diff": ["jest-diff@29.7.0", "", { "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" } }, "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw=="],
|
||||
|
||||
"expo-dev-launcher/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||
|
||||
"expo-modules-autolinking/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
|
||||
|
||||
"expo-updates/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
|
||||
|
||||
"expo/babel-preset-expo/@react-native/babel-preset": ["@react-native/babel-preset@0.79.6", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.24.7", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-computed-properties": "^7.24.7", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-function-name": "^7.25.1", "@babel/plugin-transform-literals": "^7.25.2", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-numeric-separator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", "@react-native/babel-plugin-codegen": "0.79.6", "babel-plugin-syntax-hermes-parser": "0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-H+FRO+r2Ql6b5IwfE0E7D52JhkxjeGSBSUpCXAI5zQ60zSBJ54Hwh2bBJOohXWl4J+C7gKYSAd2JHMUETu+c/A=="],
|
||||
|
||||
"express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
||||
"fallback-ui/tailwindcss/arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="],
|
||||
|
|
@ -4468,66 +4188,14 @@
|
|||
|
||||
"global-prefix/which/isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="],
|
||||
|
||||
"jest-circus/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"jest-circus/jest-matcher-utils/jest-diff": ["jest-diff@29.7.0", "", { "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" } }, "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw=="],
|
||||
|
||||
"jest-diff/pretty-format/@jest/schemas": ["@jest/schemas@30.5.0", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-/hunigyNpc4RCjC0VaW3f5RCUZVM2+WQ65qP7z083Gmvac7or2LI50XVNOtE4YPgBpV0yxYiAgorAPGniCoJmg=="],
|
||||
|
||||
"jest-diff/pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
|
||||
|
||||
"jest-environment-jsdom/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/cssstyle": ["cssstyle@2.3.0", "", { "dependencies": { "cssom": "~0.3.6" } }, "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/data-urls": ["data-urls@3.0.2", "", { "dependencies": { "abab": "^2.0.6", "whatwg-mimetype": "^3.0.0", "whatwg-url": "^11.0.0" } }, "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/html-encoding-sniffer": ["html-encoding-sniffer@3.0.0", "", { "dependencies": { "whatwg-encoding": "^2.0.0" } }, "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/http-proxy-agent": ["http-proxy-agent@5.0.0", "", { "dependencies": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" } }, "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/tough-cookie": ["tough-cookie@4.1.4", "", { "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.2.0", "url-parse": "^1.5.3" } }, "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/w3c-xmlserializer": ["w3c-xmlserializer@4.0.0", "", { "dependencies": { "xml-name-validator": "^4.0.0" } }, "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/webidl-conversions": ["webidl-conversions@7.0.0", "", {}, "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/whatwg-mimetype": ["whatwg-mimetype@3.0.0", "", {}, "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/whatwg-url": ["whatwg-url@11.0.0", "", { "dependencies": { "tr46": "^3.0.0", "webidl-conversions": "^7.0.0" } }, "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/ws": ["ws@8.20.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/xml-name-validator": ["xml-name-validator@4.0.0", "", {}, "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw=="],
|
||||
|
||||
"jest-environment-node/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"jest-haste-map/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"jest-matcher-utils/pretty-format/@jest/schemas": ["@jest/schemas@30.5.0", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-/hunigyNpc4RCjC0VaW3f5RCUZVM2+WQ65qP7z083Gmvac7or2LI50XVNOtE4YPgBpV0yxYiAgorAPGniCoJmg=="],
|
||||
|
||||
"jest-matcher-utils/pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
|
||||
|
||||
"jest-mock/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"jest-runner/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"jest-runner/source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"jest-runtime/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"jest-util/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"jest-watch-typeahead/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||
|
||||
"jest-watcher/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"jest-watcher/string-length/char-regex": ["char-regex@1.0.2", "", {}, "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="],
|
||||
|
||||
"jest-worker/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
"lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
|
@ -4624,26 +4292,18 @@
|
|||
|
||||
"ora/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
|
||||
|
||||
"ora/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
|
||||
|
||||
"parse5-htmlparser2-tree-adapter/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
|
||||
|
||||
"parse5-parser-stream/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
|
||||
|
||||
"pkg-dir/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
|
||||
|
||||
"react-native-paper/color/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
|
||||
"restore-cursor/onetime/mimic-fn": ["mimic-fn@1.2.0", "", {}, "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="],
|
||||
|
||||
"rimraf/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
|
||||
|
||||
"rimraf/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=="],
|
||||
|
||||
"send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
||||
"string-length/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||
|
||||
"sucrase/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
|
||||
|
||||
"tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q=="],
|
||||
|
|
@ -4784,8 +4444,6 @@
|
|||
|
||||
"@istanbuljs/load-nyc-config/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
||||
|
||||
"@testing-library/react-native/pretty-format/@jest/schemas/@sinclair/typebox": ["@sinclair/typebox@0.34.52", "", {}, "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||
|
||||
"@unrs/resolver-binding-wasm32-wasi/@napi-rs/wasm-runtime/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="],
|
||||
|
|
@ -4862,22 +4520,6 @@
|
|||
|
||||
"expo-updates/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||
|
||||
"expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.79.6", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.79.6" } }, "sha512-CS5OrgcMPixOyUJ/Sk/HSsKsKgyKT5P7y3CojimOQzWqRZBmoQfxdST4ugj7n1H+ebM2IKqbgovApFbqXsoX0g=="],
|
||||
|
||||
"jest-diff/pretty-format/@jest/schemas/@sinclair/typebox": ["@sinclair/typebox@0.34.52", "", {}, "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/cssstyle/cssom": ["cssom@0.3.8", "", {}, "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/http-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
|
||||
|
||||
"jest-environment-jsdom/jsdom/whatwg-url/tr46": ["tr46@3.0.0", "", { "dependencies": { "punycode": "^2.1.1" } }, "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA=="],
|
||||
|
||||
"jest-matcher-utils/pretty-format/@jest/schemas/@sinclair/typebox": ["@sinclair/typebox@0.34.52", "", {}, "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw=="],
|
||||
|
||||
"log-symbols/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
|
||||
"log-symbols/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
||||
|
|
@ -4886,8 +4528,6 @@
|
|||
|
||||
"ora/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
||||
|
||||
"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=="],
|
||||
|
||||
"react-native-paper/color/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||
|
||||
"rimraf/glob/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="],
|
||||
|
|
@ -4944,8 +4584,6 @@
|
|||
|
||||
"ora/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||
|
||||
"pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
||||
|
||||
"rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||
|
||||
"web-ui/nitro/rolldown/@rolldown/binding-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-l9Oo58x0HOP5znGzVhYW9U3e5wVuA4LAZU2AGezTmkhO1CgQRFDhDg4nneHsu/t3WniXg9QrG2nIXL/ZS8ln8Q=="],
|
||||
|
|
|
|||
1015
change-log.txt
1015
change-log.txt
File diff suppressed because it is too large
Load diff
|
|
@ -1,194 +0,0 @@
|
|||
diff --git a/apps/admin-ui/app/(drawer)/dashboard/products/add.tsx b/apps/admin-ui/app/(drawer)/dashboard/products/add.tsx
|
||||
index e227458..4465099 100644
|
||||
--- a/apps/admin-ui/app/(drawer)/dashboard/products/add.tsx
|
||||
+++ b/apps/admin-ui/app/(drawer)/dashboard/products/add.tsx
|
||||
@@ -5,6 +5,15 @@ import ProductForm from '@/src/components/ProductForm'
|
||||
import { trpc } from '@/src/trpc-client'
|
||||
import { useUploadToObjectStorage } from '@/hooks/useUploadToObjectStore'
|
||||
|
||||
+// SKUs store bucket-relative object keys, not URLs. Drop the query string and
|
||||
+// keep the last two path segments:
|
||||
+// https://<acct>.r2.cloudflarestorage.com/meatfarmer-dev/product-images/1.jpg?X-Amz-...
|
||||
+// -> product-images/1.jpg
|
||||
+const toImageKey = (url: string): string => {
|
||||
+ const parts = url.split('?')[0].split('/').filter(Boolean)
|
||||
+ return parts.slice(-2).join('/')
|
||||
+}
|
||||
+
|
||||
export default function AddProduct() {
|
||||
const createProduct = trpc.admin.product.createProduct.useMutation()
|
||||
const { refetch: refetchProducts } = trpc.admin.product.getProducts.useQuery(undefined, {
|
||||
@@ -63,7 +72,8 @@ export default function AddProduct() {
|
||||
let urlCursor = 0
|
||||
const skus = values.variants.map((variant: any, vIndex: number) => {
|
||||
const count = imageCounts[vIndex]
|
||||
- const variantUrls = allUploadUrls.slice(urlCursor, urlCursor + count)
|
||||
+ // Send keys, not the presigned URLs.
|
||||
+ const variantUrls = allUploadUrls.slice(urlCursor, urlCursor + count).map(toImageKey)
|
||||
urlCursor += count
|
||||
|
||||
return {
|
||||
diff --git a/apps/admin-ui/app/(drawer)/dashboard/products/edit.tsx b/apps/admin-ui/app/(drawer)/dashboard/products/edit.tsx
|
||||
index ac72345..69f0c97 100644
|
||||
--- a/apps/admin-ui/app/(drawer)/dashboard/products/edit.tsx
|
||||
+++ b/apps/admin-ui/app/(drawer)/dashboard/products/edit.tsx
|
||||
@@ -6,6 +6,15 @@ import ProductForm, { ProductFormRef } from '@/src/components/ProductForm';
|
||||
import { trpc } from '@/src/trpc-client';
|
||||
import { useUploadToObjectStorage } from '@/hooks/useUploadToObjectStore';
|
||||
|
||||
+// SKUs store bucket-relative object keys, not URLs. Drop the query string and
|
||||
+// keep the last two path segments:
|
||||
+// https://<acct>.r2.cloudflarestorage.com/meatfarmer-dev/product-images/1.jpg?X-Amz-...
|
||||
+// -> product-images/1.jpg
|
||||
+const toImageKey = (url: string): string => {
|
||||
+ const parts = url.split('?')[0].split('/').filter(Boolean)
|
||||
+ return parts.slice(-2).join('/')
|
||||
+}
|
||||
+
|
||||
export default function EditProduct() {
|
||||
const { id } = useLocalSearchParams();
|
||||
const productId = Number(id);
|
||||
@@ -140,9 +149,10 @@ export default function EditProduct() {
|
||||
// Existing images (mimeType === null) stay as-is
|
||||
const existingUrls = variantImages[vIndex]
|
||||
?.filter((img) => img.mimeType === null)
|
||||
- .map((img) => img.url) || []
|
||||
+ .map((img) => toImageKey(img.url)) || []
|
||||
|
||||
- const allUrls = [...existingUrls, ...newUrls]
|
||||
+ // Send keys, not URLs — the SKU stores the bucket-relative object key.
|
||||
+ const allUrls = [...existingUrls, ...newUrls.map(toImageKey)]
|
||||
|
||||
return {
|
||||
id: variant.id,
|
||||
diff --git a/apps/admin-ui/hooks/useUploadToObjectStore.ts b/apps/admin-ui/hooks/useUploadToObjectStore.ts
|
||||
index 8327cfa..25c8ee7 100644
|
||||
--- a/apps/admin-ui/hooks/useUploadToObjectStore.ts
|
||||
+++ b/apps/admin-ui/hooks/useUploadToObjectStore.ts
|
||||
@@ -43,9 +43,11 @@ export function useUploadToObjectStorage() {
|
||||
headers: { 'Content-Type': mimeType },
|
||||
});
|
||||
|
||||
- if (!response.ok) {
|
||||
- throw new Error(`Upload ${index + 1} failed with status ${response.status}`);
|
||||
- }
|
||||
+ if (!response.ok) {
|
||||
+ const body = await response.text(); // <Error><Code>…</Code></Error>
|
||||
+ console.error('upload failed', response.status, body);
|
||||
+ throw new Error(`Upload ${index + 1} failed with status ${response.status}`);
|
||||
+ }
|
||||
|
||||
// Update progress
|
||||
setProgress(prev => prev ? { ...prev, completed: prev.completed + 1 } : null);
|
||||
diff --git a/apps/backend/src/lib/s3-client.ts b/apps/backend/src/lib/s3-client.ts
|
||||
index 1f8b437..47372ca 100644
|
||||
--- a/apps/backend/src/lib/s3-client.ts
|
||||
+++ b/apps/backend/src/lib/s3-client.ts
|
||||
@@ -118,10 +118,14 @@ export async function generateSignedUrlFromS3Url(s3UrlRaw: string|null, expiresI
|
||||
|
||||
try {
|
||||
const client = getAwsClient()
|
||||
- const url = buildObjectUrl(getS3BucketName(), s3Url)
|
||||
- const signedRequest = await client.sign(url, {
|
||||
+ // X-Amz-Expires must be a QUERY param, not a header: with signQuery, aws4fetch
|
||||
+ // hoists header values into the query but still lists them in
|
||||
+ // X-Amz-SignedHeaders, and R2 then hashes the missing header as empty — which
|
||||
+ // makes the signature mismatch (S3 tolerates it, R2 does not).
|
||||
+ const url = new URL(buildObjectUrl(getS3BucketName(), s3Url))
|
||||
+ url.searchParams.set('X-Amz-Expires', String(expiresIn))
|
||||
+ const signedRequest = await client.sign(url.toString(), {
|
||||
method: 'GET',
|
||||
- headers: { 'X-Amz-Expires': String(expiresIn) },
|
||||
aws: { signQuery: true },
|
||||
})
|
||||
return signedRequest.url
|
||||
@@ -170,13 +174,13 @@ export async function generateUploadUrl(key: string, mimeType: string, expiresIn
|
||||
await createUploadUrlStatus(key)
|
||||
|
||||
const client = getAwsClient()
|
||||
- const url = buildObjectUrl(getS3BucketName(), key)
|
||||
- const signedRequest = await client.sign(url, {
|
||||
+ // Same as the GET path above: keep X-Amz-Expires in the query, and do not
|
||||
+ // sign Content-Type — leaving it unsigned means the client may send any value
|
||||
+ // without breaking the signature.
|
||||
+ const url = new URL(buildObjectUrl(getS3BucketName(), key))
|
||||
+ url.searchParams.set('X-Amz-Expires', String(expiresIn))
|
||||
+ const signedRequest = await client.sign(url.toString(), {
|
||||
method: 'PUT',
|
||||
- headers: {
|
||||
- 'Content-Type': mimeType,
|
||||
- 'X-Amz-Expires': String(expiresIn),
|
||||
- },
|
||||
aws: { signQuery: true },
|
||||
})
|
||||
|
||||
@@ -193,15 +197,22 @@ export async function generateUploadUrl(key: string, mimeType: string, expiresIn
|
||||
// return decodeURIComponent(rawKey);
|
||||
// }
|
||||
|
||||
-// New function (excludes bucket name)
|
||||
+/**
|
||||
+ * Normalise an image reference to the bucket-relative object key that SKUs store.
|
||||
+ *
|
||||
+ * Accepts either a full (presigned) URL or an already-extracted key, so callers
|
||||
+ * can send whichever they have. Drops the query string, then keeps the last two
|
||||
+ * path segments:
|
||||
+ *
|
||||
+ * https://<account>.r2.cloudflarestorage.com/meatfarmer-dev/product-images/1.jpg?X-Amz-...
|
||||
+ * -> product-images/1.jpg
|
||||
+ * product-images/1.jpg
|
||||
+ * -> product-images/1.jpg
|
||||
+ */
|
||||
export function extractKeyFromPresignedUrl(url: string): string {
|
||||
- const u = new URL(url)
|
||||
- const rawKey = u.pathname.replace(/^\/+/, '') // remove leading slash
|
||||
- const decodedKey = decodeURIComponent(rawKey)
|
||||
- // Remove bucket prefix
|
||||
- const parts = decodedKey.split('/')
|
||||
- parts.shift() // Remove bucket name
|
||||
- return parts.join('/')
|
||||
+ const withoutQuery = url.split('?')[0]
|
||||
+ const parts = withoutQuery.split('/').filter(Boolean)
|
||||
+ return decodeURIComponent(parts.slice(-2).join('/'))
|
||||
}
|
||||
|
||||
export async function claimUploadUrl(url: string): Promise<void> {
|
||||
diff --git a/apps/backend/src/trpc/apis/admin-apis/apis/product.ts b/apps/backend/src/trpc/apis/admin-apis/apis/product.ts
|
||||
index 7018961..57b51a7 100644
|
||||
--- a/apps/backend/src/trpc/apis/admin-apis/apis/product.ts
|
||||
+++ b/apps/backend/src/trpc/apis/admin-apis/apis/product.ts
|
||||
@@ -260,8 +260,6 @@ export const productRouter = router({
|
||||
await deleteImageUtil({ keys: deletedImageKeys })
|
||||
}
|
||||
|
||||
- const allUploadUrls: string[] = skus.flatMap((sku) => sku.images)
|
||||
-
|
||||
const skuInputs = skus.map((sku) => ({
|
||||
id: sku.id,
|
||||
name: sku.name ?? null,
|
||||
diff --git a/packages/ui/src/components/ImageUploaderNeo.tsx b/packages/ui/src/components/ImageUploaderNeo.tsx
|
||||
index eb5e5d7..37201f9 100644
|
||||
--- a/packages/ui/src/components/ImageUploaderNeo.tsx
|
||||
+++ b/packages/ui/src/components/ImageUploaderNeo.tsx
|
||||
@@ -11,11 +11,12 @@ import usePickImage from './use-pick-image'
|
||||
|
||||
export type { ImageUploaderNeoItem, ImageUploaderNeoPayload } from '@packages/shared'
|
||||
|
||||
-const ImageUploaderNeo: React.FC<ImageUploaderNeoProps> = ({
|
||||
+const ImageUploaderNeo: React.FC<ImageUploaderNeoProps & { testID?: string }> = ({
|
||||
images,
|
||||
onImageAdd,
|
||||
onImageRemove,
|
||||
allowMultiple = true,
|
||||
+ testID,
|
||||
}) => {
|
||||
const totalImageCount = images.length
|
||||
|
||||
@@ -60,6 +61,7 @@ const ImageUploaderNeo: React.FC<ImageUploaderNeoProps> = ({
|
||||
</View>
|
||||
))}
|
||||
<MyTouchableOpacity
|
||||
+ testID={testID}
|
||||
disabled={!allowMultiple && totalImageCount >= 1}
|
||||
onPress={handlePickImage}
|
||||
style={tw`w-1/3 px-1 mb-2`}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
// {
|
||||
// "$schema": "https://opencode.ai/config.json",
|
||||
// "permission": "allow"
|
||||
// }
|
||||
|
|
@ -29,7 +29,6 @@ export interface OrderCardActionProps<T> {
|
|||
export interface LoginFormInputs {
|
||||
mobile: string
|
||||
otp?: string
|
||||
identifier?: string
|
||||
password?: string
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,12 +11,11 @@ import usePickImage from './use-pick-image'
|
|||
|
||||
export type { ImageUploaderNeoItem, ImageUploaderNeoPayload } from '@packages/shared'
|
||||
|
||||
const ImageUploaderNeo: React.FC<ImageUploaderNeoProps & { testID?: string }> = ({
|
||||
const ImageUploaderNeo: React.FC<ImageUploaderNeoProps> = ({
|
||||
images,
|
||||
onImageAdd,
|
||||
onImageRemove,
|
||||
allowMultiple = true,
|
||||
testID,
|
||||
}) => {
|
||||
const totalImageCount = images.length
|
||||
|
||||
|
|
@ -48,7 +47,6 @@ const ImageUploaderNeo: React.FC<ImageUploaderNeoProps & { testID?: string }> =
|
|||
style={tw`w-full aspect-square rounded`}
|
||||
/>
|
||||
<MyTouchableOpacity
|
||||
testID={testID ? `${testID}-remove` : undefined}
|
||||
onPress={() =>
|
||||
onImageRemove({
|
||||
url: image.imgUrl,
|
||||
|
|
@ -62,7 +60,6 @@ const ImageUploaderNeo: React.FC<ImageUploaderNeoProps & { testID?: string }> =
|
|||
</View>
|
||||
))}
|
||||
<MyTouchableOpacity
|
||||
testID={testID}
|
||||
disabled={!allowMultiple && totalImageCount >= 1}
|
||||
onPress={handlePickImage}
|
||||
style={tw`w-1/3 px-1 mb-2`}
|
||||
|
|
|
|||
|
|
@ -212,8 +212,6 @@ const BottomDropdown: React.FC<BottomDropdownProps> = ({
|
|||
return (
|
||||
<TouchableOpacity
|
||||
key={option.value}
|
||||
testID={`${testID}-option-${option.value}`}
|
||||
accessibilityLabel={`${testID}-option-${option.value}`}
|
||||
style={[
|
||||
tw`px-4 py-3 rounded-md my-1 mx-2 flex-row items-center justify-between`,
|
||||
selected ? { backgroundColor: colors.brand50 } : tw`bg-transparent`,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ interface CheckboxProps {
|
|||
checkedColor?: string; // deprecated, use checkColor
|
||||
fillColor?: string; // new prop for box/circle fill
|
||||
checkColor?: string; // new prop for check/tick color
|
||||
testID?: string;
|
||||
}
|
||||
|
||||
const Checkbox: React.FC<CheckboxProps> = ({
|
||||
|
|
@ -26,7 +25,6 @@ const Checkbox: React.FC<CheckboxProps> = ({
|
|||
checkedColor, // deprecated
|
||||
fillColor,
|
||||
checkColor,
|
||||
testID,
|
||||
}) => {
|
||||
const { colors } = useTheme().theme;
|
||||
const fill = fillColor || colors.brand500;
|
||||
|
|
@ -41,7 +39,6 @@ const Checkbox: React.FC<CheckboxProps> = ({
|
|||
style={style}
|
||||
activeOpacity={0.7}
|
||||
disabled={disabled}
|
||||
testID={testID}
|
||||
accessibilityRole="checkbox"
|
||||
accessibilityState={{ checked, disabled }}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ interface SearchBarProps {
|
|||
containerStyle?: ViewStyle;
|
||||
onPress?: () => void;
|
||||
activeOpacity?: number;
|
||||
testID?: string;
|
||||
}
|
||||
|
||||
const SearchBar = forwardRef<any, SearchBarProps>(({
|
||||
|
|
@ -29,7 +28,6 @@ const SearchBar = forwardRef<any, SearchBarProps>(({
|
|||
containerStyle,
|
||||
onPress,
|
||||
activeOpacity = 0.8,
|
||||
testID,
|
||||
}, ref) => {
|
||||
const Wrapper = onPress ? MyTouchableOpacity : View;
|
||||
|
||||
|
|
@ -37,10 +35,8 @@ const SearchBar = forwardRef<any, SearchBarProps>(({
|
|||
style: [tw`flex-row items-center bg-white rounded-2xl px-4 h-12 mb-6 shadow-md`, { overflow: 'visible' }, containerStyle],
|
||||
onPress,
|
||||
activeOpacity,
|
||||
testID,
|
||||
} : {
|
||||
style: [tw`flex-row items-center bg-white rounded-2xl px-4 h-12 mb-6 shadow-md`, { overflow: 'visible' }, containerStyle],
|
||||
testID,
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -48,7 +44,6 @@ const SearchBar = forwardRef<any, SearchBarProps>(({
|
|||
<MaterialIcons name="search" size={24} color={theme.colors.brand500} />
|
||||
<MyTextInput
|
||||
ref={ref}
|
||||
testID={testID ? `${testID}-input` : undefined}
|
||||
style={[tw`flex-1 text-base text-gray-800 bg-transparent h-8`, { borderWidth: 0 }]}
|
||||
placeholder={placeholder}
|
||||
placeholderTextColor="#9CA3AF"
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
APP_ID=in.freshyo.adminui
|
||||
STAFF_NAME=
|
||||
STAFF_PASSWORD=
|
||||
PRODUCT_NAME="E2E Test Product"
|
||||
STORE_ID=1
|
||||
SKU1_QTY="500 g"
|
||||
SKU1_PRICE=199
|
||||
SKU1_MRP=249
|
||||
SKU2_QTY="1 kg"
|
||||
SKU2_PRICE=349
|
||||
SKU2_MRP=399
|
||||
SKU2_FLASH_PRICE=299
|
||||
SLOT_DATE=
|
||||
SLOT_HOUR=
|
||||
SLOT_MIN=
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
# Admin E2E tests (Maestro)
|
||||
|
||||
Maestro flows that drive the **admin-ui** Expo app on an Android emulator.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
tests/e2e/
|
||||
config.yaml # workspace config (entry flows + execution order)
|
||||
add-product.yaml # create a product with 2 SKUs (one flash)
|
||||
add-slot-with-product.yaml # create a slot (SLOT_DATE + SLOT_HOUR:SLOT_MIN) holding that product
|
||||
subflows/
|
||||
login.yaml # reusable login (callers invoke it conditionally)
|
||||
pick-image.yaml # OS photo-picker adapter (Android)
|
||||
set-slot-times.yaml # absolute delivery time + freeze (-10m) via native pickers
|
||||
dev/
|
||||
add-empty-slot.yaml # standalone: create a slot with no products (validate pickers)
|
||||
assets/test-product.png # seeded into the emulator gallery via `addMedia`
|
||||
run.sh # loads .env and runs `maestro test`
|
||||
.env.example # copy to .env and fill in
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Maestro CLI installed (`curl -Ls "https://get.maestro.mobile.dev" | bash`).
|
||||
- A booted Android emulator (`maestro start-device --platform android`, or Android Studio).
|
||||
- The admin-ui **dev build** installed on the emulator (`bun run --filter admin-ui android`, appId `in.freshyo.adminui`).
|
||||
- The build must be able to reach the backend (login + image upload hit the API/R2).
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
cp tests/e2e/.env.example tests/e2e/.env
|
||||
# edit tests/e2e/.env — at minimum STAFF_NAME, STAFF_PASSWORD, STORE_ID
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
bash tests/e2e/run.sh # every entry flow (ordered: add-product, then add-slot-with-product)
|
||||
bash tests/e2e/run.sh add-product.yaml
|
||||
bash tests/e2e/run.sh dev/add-empty-slot.yaml # standalone: slot only, no product
|
||||
```
|
||||
|
||||
`PRODUCT_NAME` is used **verbatim** — `add-product.yaml` creates it with that exact name
|
||||
and `add-slot-with-product.yaml` searches for it. The backend rejects duplicate names, so
|
||||
change `PRODUCT_NAME` (or delete the product) between suite runs.
|
||||
|
||||
## What `add-product.yaml` does
|
||||
|
||||
1. `addMedia` seeds `assets/test-product.png` into the emulator gallery.
|
||||
2. `launchApp` with `clearState: true` (forces login) and gallery permission.
|
||||
3. Logs in (subflow) and taps the `add-product-menu-item` quick action.
|
||||
4. Fills the product name and selects Store + Product Type.
|
||||
5. Variant 1: quantity, price, MRP, attaches an image.
|
||||
6. Adds Variant 2, fills quantity/prices, toggles **Flash Available**, sets flash price, attaches an image.
|
||||
7. Submits and asserts `Product created successfully!`.
|
||||
|
||||
## What `add-slot-with-product.yaml` does
|
||||
|
||||
1. `evalScript` computes delivery = now + 60 min and freeze = now + 50 min.
|
||||
2. Logs in and taps the `add-slot-fab`.
|
||||
3. Sets the delivery/freeze date (today) and time via the native Android pickers
|
||||
(`android:id/button1`, `toggle_mode`, `input_hour`, `input_minute`).
|
||||
4. Opens `slot-products-selector`, searches the exact `PRODUCT_NAME`, selects the
|
||||
two SKU options and taps Done.
|
||||
5. Submits and asserts `Slot created successfully!`.
|
||||
|
||||
All in-app interactions use `testID` selectors (`id:`). The exceptions are system UI —
|
||||
the OS photo picker (`subflows/pick-image.yaml`) and the native date/time pickers.
|
||||
|
||||
## Notes / gotchas
|
||||
|
||||
- The image picker flow is the most version-sensitive part; thumbs are targeted by
|
||||
the Android 13/14 Photo Picker id with a DocumentsUI fallback, and the confirm
|
||||
button by its `button_add` id.
|
||||
- Native time-picker ids (`android:id/toggle_mode`, `input_hour`, `input_minute`,
|
||||
`button1`) depend on the OS version. The date dialog defaults to today, so a run
|
||||
within ~60 min of midnight would put delivery on the next day.
|
||||
- On a reused emulator, `addMedia` images accumulate in the gallery (harmless).
|
||||
- Tests create real data on the connected backend.
|
||||
|
|
@ -1,167 +0,0 @@
|
|||
appId: ${APP_ID || "in.freshyo.adminui"}
|
||||
env:
|
||||
APP_ID: ${APP_ID || "in.freshyo.adminui"}
|
||||
STAFF_NAME: ${STAFF_NAME || ""}
|
||||
STAFF_PASSWORD: ${STAFF_PASSWORD || ""}
|
||||
PRODUCT_NAME: ${PRODUCT_NAME || "E2E Test Product"}
|
||||
STORE_ID: ${STORE_ID || 1}
|
||||
SKU1_QTY: ${SKU1_QTY || "500 g"}
|
||||
SKU1_PRICE: ${SKU1_PRICE || "199"}
|
||||
SKU1_MRP: ${SKU1_MRP || "249"}
|
||||
SKU2_QTY: ${SKU2_QTY || "1 kg"}
|
||||
SKU2_PRICE: ${SKU2_PRICE || "349"}
|
||||
SKU2_MRP: ${SKU2_MRP || "399"}
|
||||
SKU2_FLASH_PRICE: ${SKU2_FLASH_PRICE || "299"}
|
||||
tags:
|
||||
- products
|
||||
- smoke
|
||||
---
|
||||
- addMedia:
|
||||
- './assets/test-product.png'
|
||||
|
||||
- launchApp:
|
||||
clearState: true
|
||||
permissions:
|
||||
storage: allow
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: login-name-input
|
||||
timeout: 180000
|
||||
- runFlow:
|
||||
when:
|
||||
visible:
|
||||
id: login-name-input
|
||||
commands:
|
||||
- runFlow: subflows/login.yaml
|
||||
|
||||
- tapOn:
|
||||
id: add-product-menu-item
|
||||
- assertVisible:
|
||||
id: product-name-input
|
||||
|
||||
- tapOn:
|
||||
id: product-name-input
|
||||
- inputText: ${PRODUCT_NAME}
|
||||
- hideKeyboard
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: product-store-dropdown
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: product-store-dropdown
|
||||
- tapOn:
|
||||
id: product-store-dropdown-option-${STORE_ID}
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: product-type-dropdown
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: product-type-dropdown
|
||||
- tapOn:
|
||||
id: product-type-dropdown-option-item
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: variant-0-attr-0-value
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: variant-0-attr-0-value
|
||||
- inputText: ${SKU1_QTY}
|
||||
- hideKeyboard
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: variant-0-price
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: variant-0-price
|
||||
- inputText: ${SKU1_PRICE}
|
||||
- hideKeyboard
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: variant-0-market-price
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: variant-0-market-price
|
||||
- inputText: ${SKU1_MRP}
|
||||
- hideKeyboard
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: variant-0-image-add
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: variant-0-image-add
|
||||
- runFlow: subflows/pick-image.yaml
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: add-variant-button
|
||||
direction: UP
|
||||
- tapOn:
|
||||
id: add-variant-button
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: variant-1-attr-0-value
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: variant-1-attr-0-value
|
||||
- inputText: ${SKU2_QTY}
|
||||
- hideKeyboard
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: variant-1-price
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: variant-1-price
|
||||
- inputText: ${SKU2_PRICE}
|
||||
- hideKeyboard
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: variant-1-market-price
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: variant-1-market-price
|
||||
- inputText: ${SKU2_MRP}
|
||||
- hideKeyboard
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: variant-1-flash
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: variant-1-flash
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: variant-1-flash-price
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: variant-1-flash-price
|
||||
- inputText: ${SKU2_FLASH_PRICE}
|
||||
- hideKeyboard
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: variant-1-image-add
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: variant-1-image-add
|
||||
- runFlow: subflows/pick-image.yaml
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: create-product-button
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: create-product-button
|
||||
|
||||
- assertVisible: 'Product created successfully!'
|
||||
- tapOn: 'OK'
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
appId: ${APP_ID || "in.freshyo.adminui"}
|
||||
env:
|
||||
APP_ID: ${APP_ID || "in.freshyo.adminui"}
|
||||
STAFF_NAME: ${STAFF_NAME || ""}
|
||||
STAFF_PASSWORD: ${STAFF_PASSWORD || ""}
|
||||
PRODUCT_NAME: ${PRODUCT_NAME || "E2E Test Product"}
|
||||
SLOT_DATE: ${SLOT_DATE || ""}
|
||||
SLOT_HOUR: ${SLOT_HOUR || ""}
|
||||
SLOT_MIN: ${SLOT_MIN || ""}
|
||||
tags:
|
||||
- slots
|
||||
- smoke
|
||||
---
|
||||
- launchApp
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: 'login-name-input|add-product-menu-item'
|
||||
timeout: 180000
|
||||
- runFlow:
|
||||
when:
|
||||
visible:
|
||||
id: login-name-input
|
||||
commands:
|
||||
- runFlow: subflows/login.yaml
|
||||
|
||||
- openLink: freshyoadmin://dashboard/slots/add
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: delivery-date-picker
|
||||
timeout: 30000
|
||||
|
||||
- runFlow: subflows/set-slot-times.yaml
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: slot-products-selector
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: slot-products-selector
|
||||
- tapOn:
|
||||
id: slot-products-selector-search
|
||||
- inputText: ${PRODUCT_NAME}
|
||||
- hideKeyboard
|
||||
- tapOn:
|
||||
id: 'slot-products-selector-option-.*'
|
||||
index: 0
|
||||
- tapOn:
|
||||
id: 'slot-products-selector-option-.*'
|
||||
index: 1
|
||||
- tapOn:
|
||||
id: slot-products-selector-done
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: create-slot-button
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: create-slot-button
|
||||
|
||||
- assertVisible: 'Slot created successfully!'
|
||||
- tapOn: 'OK'
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 5 KiB |
|
|
@ -1,10 +0,0 @@
|
|||
flows:
|
||||
- '*.yaml'
|
||||
- '!config.yaml'
|
||||
|
||||
executionOrder:
|
||||
continueOnFailure: false
|
||||
flowsOrder:
|
||||
- add-product
|
||||
- add-slot-with-product
|
||||
- user-order
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
appId: ${APP_ID || "in.freshyo.adminui"}
|
||||
env:
|
||||
APP_ID: ${APP_ID || "in.freshyo.adminui"}
|
||||
STAFF_NAME: ${STAFF_NAME || ""}
|
||||
STAFF_PASSWORD: ${STAFF_PASSWORD || ""}
|
||||
SLOT_DATE: ${SLOT_DATE || ""}
|
||||
SLOT_HOUR: ${SLOT_HOUR || ""}
|
||||
SLOT_MIN: ${SLOT_MIN || ""}
|
||||
tags:
|
||||
- dev
|
||||
---
|
||||
- launchApp
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: 'login-name-input|add-product-menu-item'
|
||||
timeout: 180000
|
||||
- runFlow:
|
||||
when:
|
||||
visible:
|
||||
id: login-name-input
|
||||
commands:
|
||||
- runFlow: ../subflows/login.yaml
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: delivery-slots-menu-item
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: delivery-slots-menu-item
|
||||
- assertVisible:
|
||||
id: add-slot-fab
|
||||
- tapOn:
|
||||
id: add-slot-fab
|
||||
- assertVisible:
|
||||
id: delivery-date-picker
|
||||
|
||||
- runFlow: ../subflows/set-slot-times.yaml
|
||||
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: create-slot-button
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: create-slot-button
|
||||
|
||||
- assertVisible: 'Slot created successfully!'
|
||||
- tapOn: 'OK'
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
if [ ! -f .env ]; then
|
||||
echo "Missing tests/e2e/.env — copy .env.example to .env and fill it in." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
line="${line%$'\r'}"
|
||||
case "$line" in
|
||||
'' | '#'*) continue ;;
|
||||
esac
|
||||
export "$line"
|
||||
done < ./.env
|
||||
|
||||
: "${APP_ID:?APP_ID is required}"
|
||||
: "${STAFF_NAME:?STAFF_NAME is required}"
|
||||
: "${STAFF_PASSWORD:?STAFF_PASSWORD is required}"
|
||||
: "${PRODUCT_NAME:?PRODUCT_NAME is required}"
|
||||
: "${STORE_ID:?STORE_ID is required}"
|
||||
: "${SLOT_DATE:?SLOT_DATE is required (YYYY-MM-DD, must be today)}"
|
||||
: "${SLOT_HOUR:?SLOT_HOUR is required (delivery hour, 24h zero-padded)}"
|
||||
: "${SLOT_MIN:?SLOT_MIN is required (delivery minute, zero-padded)}"
|
||||
|
||||
export PRODUCT_NAME
|
||||
|
||||
if [ "$#" -eq 0 ]; then
|
||||
set -- .
|
||||
fi
|
||||
|
||||
freeze_total=$((10#$SLOT_HOUR * 60 + 10#$SLOT_MIN - 10))
|
||||
SLOT_FREEZE_HOUR=$(printf '%02d' $((freeze_total / 60)))
|
||||
SLOT_FREEZE_MIN=$(printf '%02d' $((freeze_total % 60)))
|
||||
export SLOT_FREEZE_HOUR SLOT_FREEZE_MIN
|
||||
|
||||
maestro test \
|
||||
-e APP_ID="$APP_ID" \
|
||||
-e STAFF_NAME="$STAFF_NAME" \
|
||||
-e STAFF_PASSWORD="$STAFF_PASSWORD" \
|
||||
-e PRODUCT_NAME="$PRODUCT_NAME" \
|
||||
-e STORE_ID="$STORE_ID" \
|
||||
-e SKU1_QTY="${SKU1_QTY:-}" \
|
||||
-e SKU1_PRICE="${SKU1_PRICE:-}" \
|
||||
-e SKU1_MRP="${SKU1_MRP:-}" \
|
||||
-e SKU2_QTY="${SKU2_QTY:-}" \
|
||||
-e SKU2_PRICE="${SKU2_PRICE:-}" \
|
||||
-e SKU2_MRP="${SKU2_MRP:-}" \
|
||||
-e SKU2_FLASH_PRICE="${SKU2_FLASH_PRICE:-}" \
|
||||
-e SLOT_DATE="$SLOT_DATE" \
|
||||
-e SLOT_HOUR="$SLOT_HOUR" \
|
||||
-e SLOT_MIN="$SLOT_MIN" \
|
||||
-e SLOT_FREEZE_HOUR="$SLOT_FREEZE_HOUR" \
|
||||
-e SLOT_FREEZE_MIN="$SLOT_FREEZE_MIN" \
|
||||
-e USER_APP_ID="${USER_APP_ID:-in.freshyo.app}" \
|
||||
-e USER_MOBILE="${USER_MOBILE:-}" \
|
||||
-e USER_PASSWORD="${USER_PASSWORD:-}" \
|
||||
"$@"
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
appId: ${USER_APP_ID}
|
||||
env:
|
||||
USER_MOBILE: ${USER_MOBILE || ""}
|
||||
USER_PASSWORD: ${USER_PASSWORD || ""}
|
||||
---
|
||||
- tapOn:
|
||||
id: user-login-mobile
|
||||
- inputText: ${USER_MOBILE}
|
||||
- pressKey: enter
|
||||
- tapOn:
|
||||
id: user-login-other-ways
|
||||
- tapOn:
|
||||
id: user-login-password
|
||||
- inputText: ${USER_PASSWORD}
|
||||
- pressKey: enter
|
||||
- tapOn:
|
||||
id: user-login-submit
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
appId: ${APP_ID || "in.freshyo.adminui"}
|
||||
env:
|
||||
STAFF_NAME: ${STAFF_NAME || ""}
|
||||
STAFF_PASSWORD: ${STAFF_PASSWORD || ""}
|
||||
---
|
||||
- tapOn:
|
||||
id: login-name-input
|
||||
- inputText: ${STAFF_NAME}
|
||||
- tapOn:
|
||||
id: login-password-input
|
||||
- inputText: ${STAFF_PASSWORD}
|
||||
- hideKeyboard
|
||||
- tapOn:
|
||||
id: login-button
|
||||
- assertVisible:
|
||||
id: add-product-menu-item
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
appId: ${APP_ID || "in.freshyo.adminui"}
|
||||
---
|
||||
- runFlow:
|
||||
when:
|
||||
platform: Android
|
||||
commands:
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: 'com\.(google\.)?android\.providers\.media\.module:id/icon_thumbnail'
|
||||
timeout: 15000
|
||||
|
||||
- tapOn:
|
||||
id: 'com\.(google\.)?android\.providers\.media\.module:id/icon_thumbnail'
|
||||
index: 0
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: 'com\.(google\.)?android\.providers\.media\.module:id/button_add'
|
||||
timeout: 10000
|
||||
- tapOn:
|
||||
id: 'com\.(google\.)?android\.providers\.media\.module:id/button_add'
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: app-root
|
||||
timeout: 15000
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
appId: ${APP_ID || "in.freshyo.adminui"}
|
||||
---
|
||||
- tapOn:
|
||||
id: delivery-date-picker
|
||||
- tapOn:
|
||||
id: 'android:id/button1'
|
||||
|
||||
- tapOn:
|
||||
id: delivery-time-picker
|
||||
- tapOn:
|
||||
id: 'android:id/toggle_mode'
|
||||
optional: true
|
||||
- tapOn:
|
||||
id: 'android:id/input_hour'
|
||||
- eraseText
|
||||
- inputText: ${SLOT_HOUR}
|
||||
- tapOn:
|
||||
id: 'android:id/input_minute'
|
||||
- eraseText
|
||||
- inputText: ${SLOT_MIN}
|
||||
- tapOn:
|
||||
id: 'android:id/button1'
|
||||
|
||||
- tapOn:
|
||||
id: freeze-date-picker
|
||||
- tapOn:
|
||||
id: 'android:id/button1'
|
||||
|
||||
- tapOn:
|
||||
id: freeze-time-picker
|
||||
- tapOn:
|
||||
id: 'android:id/toggle_mode'
|
||||
optional: true
|
||||
- tapOn:
|
||||
id: 'android:id/input_hour'
|
||||
- eraseText
|
||||
- inputText: ${SLOT_FREEZE_HOUR}
|
||||
- tapOn:
|
||||
id: 'android:id/input_minute'
|
||||
- eraseText
|
||||
- inputText: ${SLOT_FREEZE_MIN}
|
||||
- tapOn:
|
||||
id: 'android:id/button1'
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
appId: ${USER_APP_ID}
|
||||
env:
|
||||
USER_APP_ID: ${USER_APP_ID || "in.freshyo.app"}
|
||||
USER_MOBILE: ${USER_MOBILE || ""}
|
||||
USER_PASSWORD: ${USER_PASSWORD || ""}
|
||||
PRODUCT_NAME: ${PRODUCT_NAME || "E2E Test Product"}
|
||||
SLOT_DATE: ${SLOT_DATE || ""}
|
||||
SLOT_HOUR: ${SLOT_HOUR || ""}
|
||||
SLOT_MIN: ${SLOT_MIN || ""}
|
||||
tags:
|
||||
- user
|
||||
- smoke
|
||||
---
|
||||
- launchApp:
|
||||
clearState: true
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
text: 'Next|Home'
|
||||
timeout: 60000
|
||||
|
||||
- tapOn:
|
||||
text: 'Next'
|
||||
optional: true
|
||||
- waitForAnimationToEnd
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: home-search
|
||||
timeout: 30000
|
||||
- tapOn:
|
||||
id: home-search
|
||||
- tapOn:
|
||||
id: search-input-input
|
||||
- inputText: ${PRODUCT_NAME}
|
||||
- pressKey: enter
|
||||
- tapOn: 'Add to Cart'
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: 'slot-${SLOT_DATE}-${SLOT_HOUR}-${SLOT_MIN}'
|
||||
timeout: 20000
|
||||
- tapOn:
|
||||
id: 'slot-${SLOT_DATE}-${SLOT_HOUR}-${SLOT_MIN}'
|
||||
- tapOn:
|
||||
id: add-to-cart-confirm
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: go-to-cart
|
||||
timeout: 20000
|
||||
- tapOn:
|
||||
id: go-to-cart
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: checkout-button
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: checkout-button
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: 'user-login-mobile|place-order-button'
|
||||
timeout: 30000
|
||||
- runFlow:
|
||||
when:
|
||||
visible:
|
||||
id: user-login-mobile
|
||||
commands:
|
||||
- runFlow: subflows/login-user.yaml
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: home-search
|
||||
timeout: 60000
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: go-to-cart
|
||||
timeout: 20000
|
||||
- tapOn:
|
||||
id: go-to-cart
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: checkout-button
|
||||
direction: DOWN
|
||||
- tapOn:
|
||||
id: checkout-button
|
||||
|
||||
- extendedWaitUntil:
|
||||
visible:
|
||||
id: address-option-0
|
||||
timeout: 30000
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: place-order-button
|
||||
direction: DOWN
|
||||
- runFlow:
|
||||
when:
|
||||
visible:
|
||||
id: select-address-error
|
||||
commands:
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: address-option-0
|
||||
direction: UP
|
||||
- tapOn:
|
||||
id: address-option-0
|
||||
- scrollUntilVisible:
|
||||
element:
|
||||
id: place-order-button
|
||||
direction: DOWN
|
||||
|
||||
- extendedWaitUntil:
|
||||
notVisible:
|
||||
id: select-address-error
|
||||
timeout: 15000
|
||||
- tapOn:
|
||||
id: place-order-button
|
||||
|
||||
- assertVisible: 'Order Placed Successfully!'
|
||||
Loading…
Add table
Reference in a new issue