From 8b2c12b80d6ae408206ae292e914eff4bfd469f6 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Tue, 23 Sep 2025 23:24:38 +0530 Subject: [PATCH 01/43] Fixed navigation to home --- frontend/src/components/Dialog/FaceSearchDialog.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Dialog/FaceSearchDialog.tsx b/frontend/src/components/Dialog/FaceSearchDialog.tsx index 17c9073c4..a083a9c66 100644 --- a/frontend/src/components/Dialog/FaceSearchDialog.tsx +++ b/frontend/src/components/Dialog/FaceSearchDialog.tsx @@ -17,10 +17,12 @@ import { hideLoader, showLoader } from '@/features/loaderSlice'; import { usePictoMutation } from '@/hooks/useQueryExtension'; import { fetchSearchedFaces } from '@/api/api-functions'; import { showInfoDialog } from '@/features/infoDialogSlice'; +import { useNavigate } from 'react-router'; +import { ROUTES } from '@/constants/routes'; export function FaceSearchDialog() { const [isDialogOpen, setIsDialogOpen] = useState(false); const { pickSingleFile } = useFile({ title: 'Select File' }); - + const navigate = useNavigate(); const dispatch = useDispatch(); const { mutate: getSearchImages } = usePictoMutation({ @@ -56,6 +58,7 @@ export function FaceSearchDialog() { }); const handlePickFile = async () => { + navigate(`/${ROUTES.HOME}`); setIsDialogOpen(false); const filePath = await pickSingleFile(); if (filePath) { From 52a8a57421fdc34cdb01366cddc7781db1fd7510 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Tue, 23 Sep 2025 23:55:12 +0530 Subject: [PATCH 02/43] Removed console logs --- frontend/src/components/Media/MediaView.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/components/Media/MediaView.tsx b/frontend/src/components/Media/MediaView.tsx index e59e3c354..d4e01ab7d 100644 --- a/frontend/src/components/Media/MediaView.tsx +++ b/frontend/src/components/Media/MediaView.tsx @@ -35,7 +35,6 @@ export function MediaView({ onClose, images, type = 'image' }: MediaViewProps) { } return null; }, [images, currentViewIndex]); - console.log(currentViewIndex); // Local UI state const [showInfo, setShowInfo] = useState(false); From 7b73b34a160b4cdb4daf09334dd69005b7303da2 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 25 Sep 2025 17:00:45 +0530 Subject: [PATCH 03/43] Testing webcam permissions --- frontend/src/components/Dialog/FaceSearchDialog.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Dialog/FaceSearchDialog.tsx b/frontend/src/components/Dialog/FaceSearchDialog.tsx index a083a9c66..09c9fb2e5 100644 --- a/frontend/src/components/Dialog/FaceSearchDialog.tsx +++ b/frontend/src/components/Dialog/FaceSearchDialog.tsx @@ -57,6 +57,16 @@ export function FaceSearchDialog() { }, }); + const handleWebCam = async () => { + try { + const stream = await navigator.mediaDevices.getUserMedia({ video: true }); + const video = document.querySelector('video'); + if (video) video.srcObject = stream; + } catch (err) { + console.error('Webcam error:', err); + } + }; + const handlePickFile = async () => { navigate(`/${ROUTES.HOME}`); setIsDialogOpen(false); @@ -104,7 +114,7 @@ export function FaceSearchDialog() { - + Face Detection Search - Search for images containing specific faces by uploading a photo or - using your webcam. + {showCamera + ? 'Capture a photo to search for matching faces' + : 'Search for images containing specific faces by uploading a photo or using your webcam.'} -
- + {!showCamera ? ( + <> +
+ + + +
+ +

+ PictoPy will analyze the face and find matching images in your + gallery. +

+ + ) : ( +
+
+ - -
+ -

- PictoPy will analyze the face and find matching images in your - gallery. -

+ {capturedImageUrl && ( +
+
+ Photo captured! Click "Save & Search" to save locally and + search for faces. +
+
+ + +
+
+ )} +
+
+ )}
); diff --git a/frontend/src/components/WebCam/WebCamComponent.tsx b/frontend/src/components/WebCam/WebCamComponent.tsx new file mode 100644 index 000000000..726f4c6a4 --- /dev/null +++ b/frontend/src/components/WebCam/WebCamComponent.tsx @@ -0,0 +1,49 @@ +import React, { useState } from 'react'; +import Webcam from 'react-webcam'; +import { Dispatch, SetStateAction } from 'react'; +interface WebcamComponentType { + setShowCamera: Dispatch>; + setImageUrl: Dispatch>; +} +const videoConstraints = { + facingMode: 'user', +}; +function WebcamComponent({ setShowCamera, setImageUrl }: WebcamComponentType) { + const webcamRef = React.useRef(null); + const capture = React.useCallback(() => { + const imageSrc = webcamRef.current.getScreenshot(); + setImageUrl(imageSrc); + setShowCamera(false); + }, [webcamRef]); + return ( +
+
+ + +
+
+ ); +} +export default WebcamComponent; From 1e4b9008899474ba929a0050a751f5eb357941f7 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Sun, 5 Oct 2025 15:53:53 +0530 Subject: [PATCH 06/43] Added dialog box for those device that dont support webcam --- .../src/components/Dialog/FaceSearchDialog.tsx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Dialog/FaceSearchDialog.tsx b/frontend/src/components/Dialog/FaceSearchDialog.tsx index ac0c47a63..1469936e8 100644 --- a/frontend/src/components/Dialog/FaceSearchDialog.tsx +++ b/frontend/src/components/Dialog/FaceSearchDialog.tsx @@ -20,6 +20,7 @@ import { showInfoDialog } from '@/features/infoDialogSlice'; import { useNavigate } from 'react-router'; import { ROUTES } from '@/constants/routes'; import WebcamComponent from '../WebCam/WebCamComponent'; + export function FaceSearchDialog() { const [isDialogOpen, setIsDialogOpen] = useState(false); const [showCamera, setShowCamera] = useState(false); @@ -95,8 +96,21 @@ export function FaceSearchDialog() { } }; const handleWebCam = async () => { - setShowCamera(true); - setCapturedImageUrl(null); + try { + await navigator.mediaDevices.getUserMedia({ video: true }); + + setShowCamera(true); + setCapturedImageUrl(null); + } catch (error) { + dispatch( + showInfoDialog({ + title: "Webcam doesn't support", + message: + 'Webcam is not supported or access was denied on this device.', + variant: 'error', + }), + ); + } }; const handlePickFile = async () => { From b9a36dd582178f2244a230dfaf04e938d8f083b3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 5 Oct 2025 16:51:28 +0530 Subject: [PATCH 07/43] Revert "Removed console logs" This reverts commit 52a8a57421fdc34cdb01366cddc7781db1fd7510. good --- frontend/src/components/Media/MediaView.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/components/Media/MediaView.tsx b/frontend/src/components/Media/MediaView.tsx index d4e01ab7d..e59e3c354 100644 --- a/frontend/src/components/Media/MediaView.tsx +++ b/frontend/src/components/Media/MediaView.tsx @@ -35,6 +35,7 @@ export function MediaView({ onClose, images, type = 'image' }: MediaViewProps) { } return null; }, [images, currentViewIndex]); + console.log(currentViewIndex); // Local UI state const [showInfo, setShowInfo] = useState(false); From 2c037c85a1156e6ad6df913168f55e143f0085df Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Mon, 13 Oct 2025 16:22:56 +0530 Subject: [PATCH 08/43] Reverted some changes to 7b73b34 commit and fixed the closing of dialog after selecting a file --- .../components/Dialog/FaceSearchDialog.tsx | 173 ++++-------------- 1 file changed, 37 insertions(+), 136 deletions(-) diff --git a/frontend/src/components/Dialog/FaceSearchDialog.tsx b/frontend/src/components/Dialog/FaceSearchDialog.tsx index 1469936e8..c97eec372 100644 --- a/frontend/src/components/Dialog/FaceSearchDialog.tsx +++ b/frontend/src/components/Dialog/FaceSearchDialog.tsx @@ -19,12 +19,11 @@ import { fetchSearchedFaces } from '@/api/api-functions'; import { showInfoDialog } from '@/features/infoDialogSlice'; import { useNavigate } from 'react-router'; import { ROUTES } from '@/constants/routes'; -import WebcamComponent from '../WebCam/WebCamComponent'; export function FaceSearchDialog() { const [isDialogOpen, setIsDialogOpen] = useState(false); - const [showCamera, setShowCamera] = useState(false); - const [capturedImageUrl, setCapturedImageUrl] = useState(null); + //const [showCamera, setShowCamera] = useState(false); + //const [capturedImageUrl, setCapturedImageUrl] = useState(null); const { pickSingleFile } = useFile({ title: 'Select File' }); const navigate = useNavigate(); const dispatch = useDispatch(); @@ -60,47 +59,10 @@ export function FaceSearchDialog() { ); }, }); - const saveImageLocally = async (base64Image: string) => { - try { - // Convert base64 to blob - const response = await fetch(base64Image); - const blob = await response.blob(); - - // Create a temporary URL for the blob - const url = window.URL.createObjectURL(blob); - - // Create a temporary anchor element and trigger download - const link = document.createElement('a'); - link.href = url; - link.download = `face-search-${Date.now()}.jpg`; - document.body.appendChild(link); - link.click(); - - // Clean up - document.body.removeChild(link); - window.URL.revokeObjectURL(url); - - // Also use the image for face search - dispatch(startSearch(base64Image)); - dispatch(showLoader('Searching faces...')); - getSearchImages(base64Image); - } catch (error) { - console.error('Error saving image:', error); - dispatch( - showInfoDialog({ - title: 'Save Failed', - message: 'There was an error saving the captured image.', - variant: 'error', - }), - ); - } - }; const handleWebCam = async () => { + navigate(`/${ROUTES.HOME}`); try { await navigator.mediaDevices.getUserMedia({ video: true }); - - setShowCamera(true); - setCapturedImageUrl(null); } catch (error) { dispatch( showInfoDialog({ @@ -115,29 +77,14 @@ export function FaceSearchDialog() { const handlePickFile = async () => { navigate(`/${ROUTES.HOME}`); - setIsDialogOpen(false); const filePath = await pickSingleFile(); if (filePath) { + setIsDialogOpen(false); dispatch(startSearch(filePath)); dispatch(showLoader('Searching faces...')); getSearchImages(filePath); } }; - const handleSaveCapturedImage = () => { - if (capturedImageUrl) { - console.log(capturedImageUrl); - saveImageLocally(capturedImageUrl); - setShowCamera(false); - setCapturedImageUrl(null); - setIsDialogOpen(false); - navigate(`/${ROUTES.HOME}`); - } - }; - - const handleCancelWebcam = () => { - setShowCamera(false); - setCapturedImageUrl(null); - }; return ( @@ -151,93 +98,47 @@ export function FaceSearchDialog() { Face Detection Search - + Face Detection Search - {showCamera - ? 'Capture a photo to search for matching faces' - : 'Search for images containing specific faces by uploading a photo or using your webcam.'} + Search for images containing specific faces by uploading a photo or + using your webcam. - {!showCamera ? ( - <> -
- - - -
- -

- PictoPy will analyze the face and find matching images in your - gallery. -

- - ) : ( -
-
- +
+ - + +
- {capturedImageUrl && ( -
-
- Photo captured! Click "Save & Search" to save locally and - search for faces. -
-
- - -
-
- )} -
-
- )} +

+ PictoPy will analyze the face and find matching images in your + gallery. +

); From 79c9b6768297e47aa54ecbfda7740c9591ed066c Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Tue, 14 Oct 2025 23:12:53 +0530 Subject: [PATCH 09/43] testing on windows --- .../components/Dialog/FaceSearchDialog.tsx | 111 ++++++------ .../src/components/WebCam/WebCamComponent.tsx | 164 ++++++++++++++++++ 2 files changed, 224 insertions(+), 51 deletions(-) create mode 100644 frontend/src/components/WebCam/WebCamComponent.tsx diff --git a/frontend/src/components/Dialog/FaceSearchDialog.tsx b/frontend/src/components/Dialog/FaceSearchDialog.tsx index 6c9358286..16c88a670 100644 --- a/frontend/src/components/Dialog/FaceSearchDialog.tsx +++ b/frontend/src/components/Dialog/FaceSearchDialog.tsx @@ -19,9 +19,11 @@ import { fetchSearchedFaces } from '@/api/api-functions'; import { showInfoDialog } from '@/features/infoDialogSlice'; import { useNavigate } from 'react-router'; import { ROUTES } from '@/constants/routes'; +import WebcamComponent from '../WebCam/WebCamComponent'; + export function FaceSearchDialog() { const [isDialogOpen, setIsDialogOpen] = useState(false); - const [setDevices] = useState([]); + const [showCamera, setShowCamera] = useState(false); const { pickSingleFile } = useFile({ title: 'Select File' }); const navigate = useNavigate(); const dispatch = useDispatch(); @@ -83,60 +85,67 @@ export function FaceSearchDialog() { } }; return ( - - - - - - - Face Detection Search - - Search for images containing specific faces by uploading a photo or - using your webcam. - - - -
+ <> + + + + + + Face Detection Search + + Search for images containing specific faces by uploading a photo + or using your webcam. + + - -
+
+ + + +
+ +

+ PictoPy will analyze the face and find matching images in your + gallery. +

+
+
-

- PictoPy will analyze the face and find matching images in your - gallery. -

-
- + setShowCamera(false)} + /> + ); } diff --git a/frontend/src/components/WebCam/WebCamComponent.tsx b/frontend/src/components/WebCam/WebCamComponent.tsx new file mode 100644 index 000000000..fa9057a78 --- /dev/null +++ b/frontend/src/components/WebCam/WebCamComponent.tsx @@ -0,0 +1,164 @@ +import { useState, useRef, useCallback } from 'react'; +import Webcam from 'react-webcam'; +import { X, RotateCcw, Search } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { useDispatch } from 'react-redux'; +import { startSearch, setResults, clearSearch } from '@/features/searchSlice'; +import type { Image } from '@/types/Media'; +import { hideLoader, showLoader } from '@/features/loaderSlice'; +import { usePictoMutation } from '@/hooks/useQueryExtension'; +import { fetchSearchedFaces } from '@/api/api-functions'; +import { showInfoDialog } from '@/features/infoDialogSlice'; + +const videoConstraints = { + facingMode: 'user', +}; + +interface WebcamComponentProps { + isOpen: boolean; + onClose: () => void; +} + +function WebcamComponent({ isOpen, onClose }: WebcamComponentProps) { + const [showCamera, setShowCamera] = useState(true); + const [capturedImageUrl, setCapturedImageUrl] = useState(null); + const webcamRef = useRef(null); + const dispatch = useDispatch(); + + const { mutate: getSearchImages } = usePictoMutation({ + mutationFn: async (path: string) => fetchSearchedFaces({ path }), + onSuccess: (data) => { + const result = data?.data as Image[]; + dispatch(hideLoader()); + handleClose(); + if (result && result.length > 0) { + dispatch(setResults(result)); + } else { + dispatch(clearSearch()); + dispatch( + showInfoDialog({ + title: 'No Matches Found', + message: + "We couldn't find any matching faces in your gallery for this photo.", + variant: 'info', + }), + ); + } + }, + onError: () => { + dispatch(hideLoader()); + dispatch( + showInfoDialog({ + title: 'Search Failed', + message: 'There was an error while searching for faces.', + variant: 'error', + }), + ); + }, + }); + + const capture = useCallback(() => { + if (webcamRef.current) { + const imageSrc = webcamRef.current.getScreenshot(); + setCapturedImageUrl(imageSrc); + setShowCamera(false); + } + }, [webcamRef]); + + const handleRetake = () => { + setCapturedImageUrl(null); + setShowCamera(true); + }; + + const handleSearchCapturedImage = () => { + if (capturedImageUrl) { + dispatch(startSearch(capturedImageUrl)); + dispatch(showLoader('Searching faces...')); + getSearchImages(capturedImageUrl); + } + }; + + const handleClose = () => { + setShowCamera(true); + setCapturedImageUrl(null); + onClose(); + }; + + return ( + + + + + {capturedImageUrl ? 'Captured Photo' : 'Take a Photo'} + + + {capturedImageUrl + ? 'Review your photo and search for matching faces' + : 'Position your face in the frame and capture'} + + + +
+ {showCamera && !capturedImageUrl ? ( +
+ + +
+ ) : capturedImageUrl ? ( +
+ Captured +
+ + + +
+
+ ) : null} +
+
+
+ ); +} + +export default WebcamComponent; From 994b94316cf258c8d5966a392e6debd0e4ea5963 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 11:30:33 +0530 Subject: [PATCH 10/43] Implemented Base64 to image route --- backend/app/routes/face_clusters.py | 85 ++++++++------------- backend/app/schemas/images.py | 4 + backend/app/utils/faceSearch.py | 95 ++++++++++++++++++++++++ docs/backend/backend_python/openapi.json | 53 +++++++++++++ 4 files changed, 183 insertions(+), 54 deletions(-) create mode 100644 backend/app/utils/faceSearch.py diff --git a/backend/app/routes/face_clusters.py b/backend/app/routes/face_clusters.py index 9987b49d8..9bb607009 100644 --- a/backend/app/routes/face_clusters.py +++ b/backend/app/routes/face_clusters.py @@ -1,9 +1,9 @@ import logging +import base64 import uuid import os from typing import Optional, List, Dict, Any from pydantic import BaseModel -from app.config.settings import CONFIDENCE_PERCENT, DEFAULT_FACENET_MODEL from fastapi import APIRouter, HTTPException, status from app.database.face_clusters import ( db_get_cluster_by_id, @@ -11,9 +11,6 @@ db_get_all_clusters_with_face_counts, db_get_images_by_cluster_id, # Add this import ) -from app.database.faces import get_all_face_embeddings -from app.models.FaceDetector import FaceDetector -from app.models.FaceNet import FaceNet from app.schemas.face_clusters import ( RenameClusterRequest, RenameClusterResponse, @@ -26,8 +23,8 @@ GetClusterImagesData, ImageInCluster, ) -from app.schemas.images import AddSingleImageRequest -from app.utils.FaceNet import FaceNet_util_cosine_similarity +from app.schemas.images import AddSingleBase64ImageRequest, AddSingleImageRequest +from app.utils.faceSearch import perform_face_search class BoundingBox(BaseModel): @@ -247,56 +244,36 @@ def face_tagging(payload: AddSingleImageRequest): message="The provided path is not a valid file", ).model_dump(), ) + return perform_face_search(image_path) + + +@router.post("/face-search-base64") +def face_search_base64(payload: AddSingleBase64ImageRequest): + base64_data = payload.base64 + + if not base64_data: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ErrorResponse( + success=False, + error="No base64 data", + message="Base64 image data is required.", + ).model_dump(), + ) - fd = FaceDetector() - fn = FaceNet(DEFAULT_FACENET_MODEL) try: - matches = [] - image_id = str(uuid.uuid4()) - result = fd.detect_faces(image_id, image_path, forSearch=True) - if not result or result["num_faces"] == 0: - return GetAllImagesResponse( - success=True, - message=f"Successfully retrieved {len(matches)} images", - data=[], - ) + image_bytes = base64.b64decode(base64_data.split(",")[-1]) + image_id = str(uuid.uuid4())[:8] + temp_dir = "temp_uploads" + os.makedirs(temp_dir, exist_ok=True) + image_path = os.path.join(temp_dir, f"{image_id}.jpeg") - process_face = result["processed_faces"][0] - new_embedding = fn.get_embedding(process_face) + with open(image_path, "wb") as f: + f.write(image_bytes) + + result = perform_face_search(image_path) + return result - images = get_all_face_embeddings() - if len(images) == 0: - return GetAllImagesResponse( - success=True, - message=f"Successfully retrieved {len(matches)} images", - data=[], - ) - else: - for image in images: - max_similarity = 0 - similarity = FaceNet_util_cosine_similarity( - new_embedding, image["embeddings"] - ) - max_similarity = max(max_similarity, similarity) - if max_similarity >= CONFIDENCE_PERCENT: - matches.append( - ImageData( - id=image["id"], - path=image["path"], - folder_id=image["folder_id"], - thumbnailPath=image["thumbnailPath"], - metadata=image["metadata"], - isTagged=image["isTagged"], - tags=image["tags"], - bboxes=image["bbox"], - ) - ) - - return GetAllImagesResponse( - success=True, - message=f"Successfully retrieved {len(matches)} images", - data=matches, - ) finally: - fd.close() - fn.close() + if os.path.exists(image_path): + os.remove(image_path) diff --git a/backend/app/schemas/images.py b/backend/app/schemas/images.py index ac1400159..3a9235403 100644 --- a/backend/app/schemas/images.py +++ b/backend/app/schemas/images.py @@ -7,6 +7,10 @@ class AddSingleImageRequest(BaseModel): path: str +class AddSingleBase64ImageRequest(BaseModel): + base64: str + + class AddMultipleImagesRequest(BaseModel): paths: List[str] diff --git a/backend/app/utils/faceSearch.py b/backend/app/utils/faceSearch.py new file mode 100644 index 000000000..10321610a --- /dev/null +++ b/backend/app/utils/faceSearch.py @@ -0,0 +1,95 @@ +import uuid +from typing import Optional, List, Dict, Any +from pydantic import BaseModel +from app.config.settings import CONFIDENCE_PERCENT, DEFAULT_FACENET_MODEL +from app.database.faces import get_all_face_embeddings +from app.models.FaceDetector import FaceDetector +from app.models.FaceNet import FaceNet +from app.utils.FaceNet import FaceNet_util_cosine_similarity + + +class BoundingBox(BaseModel): + x: float + y: float + width: float + height: float + + +class ImageData(BaseModel): + id: str + path: str + folder_id: str + thumbnailPath: str + metadata: Dict[str, Any] + isTagged: bool + tags: Optional[List[str]] = None + bboxes: BoundingBox + + +class GetAllImagesResponse(BaseModel): + success: bool + message: str + data: List[ImageData] + + +def perform_face_search(image_path: str) -> GetAllImagesResponse: + """ + Performs face detection, embedding generation, and similarity search. + + Args: + image_path (str): Path to the image file to process. + + Returns: + GetAllImagesResponse: Search result containing matched images. + """ + fd = FaceDetector() + fn = FaceNet(DEFAULT_FACENET_MODEL) + + try: + matches = [] + image_id = str(uuid.uuid4()) + + result = fd.detect_faces(image_id, image_path, forSearch=True) + if not result or result["num_faces"] == 0: + return GetAllImagesResponse( + success=True, + message="No faces detected in the image.", + data=[], + ) + + process_face = result["processed_faces"][0] + new_embedding = fn.get_embedding(process_face) + + images = get_all_face_embeddings() + if not images: + return GetAllImagesResponse( + success=True, + message="No face embeddings available for comparison.", + data=[], + ) + + for image in images: + similarity = FaceNet_util_cosine_similarity(new_embedding, image["embeddings"]) + if similarity >= CONFIDENCE_PERCENT: + matches.append( + ImageData( + id=image["id"], + path=image["path"], + folder_id=image["folder_id"], + thumbnailPath=image["thumbnailPath"], + metadata=image["metadata"], + isTagged=image["isTagged"], + tags=image["tags"], + bboxes=image["bbox"], + ) + ) + + return GetAllImagesResponse( + success=True, + message=f"Successfully retrieved {len(matches)} matching images.", + data=matches, + ) + + finally: + fd.close() + fn.close() diff --git a/docs/backend/backend_python/openapi.json b/docs/backend/backend_python/openapi.json index b65874f03..1a3476925 100644 --- a/docs/backend/backend_python/openapi.json +++ b/docs/backend/backend_python/openapi.json @@ -1094,6 +1094,45 @@ } } }, + "/face-clusters/face-search-base64": { + "post": { + "tags": [ + "Face Clusters" + ], + "summary": "Face Search Base64", + "operationId": "face_search_base64_face_clusters_face_search_base64_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AddSingleBase64ImageRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, "/user-preferences/": { "get": { "tags": [ @@ -1288,6 +1327,19 @@ ], "title": "AddFolderResponse" }, + "AddSingleBase64ImageRequest": { + "properties": { + "base64": { + "type": "string", + "title": "Base64" + } + }, + "type": "object", + "required": [ + "base64" + ], + "title": "AddSingleBase64ImageRequest" + }, "AddSingleImageRequest": { "properties": { "path": { @@ -2003,6 +2055,7 @@ "metadata": { "anyOf": [ { + "additionalProperties": true, "type": "object" }, { From ed5168b73093762f0d90b96e48409774c0ec76f1 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 11:31:06 +0530 Subject: [PATCH 11/43] Added routes in frontend --- frontend/src/api/api-functions/face_clusters.ts | 14 ++++++++++++++ frontend/src/api/apiEndpoints.ts | 1 + .../src/components/Dialog/FaceSearchDialog.tsx | 15 ++++++++------- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/frontend/src/api/api-functions/face_clusters.ts b/frontend/src/api/api-functions/face_clusters.ts index 5a079eb9e..14268c16a 100644 --- a/frontend/src/api/api-functions/face_clusters.ts +++ b/frontend/src/api/api-functions/face_clusters.ts @@ -15,6 +15,10 @@ export interface FetchSearchedFacesRequest { path: string; } +export interface FetchSearchedFacesBase64Request { + base64_data: string; +} + export const fetchAllClusters = async (): Promise => { const response = await apiClient.get( faceClustersEndpoints.getAllClusters, @@ -50,3 +54,13 @@ export const fetchSearchedFaces = async ( ); return response.data; }; + +export const fetchSearchedFacesBase64 = async ( + request: FetchSearchedFacesBase64Request, +): Promise => { + const response = await apiClient.post( + faceClustersEndpoints.searchForFacesBase64, + request, + ); + return response.data; +}; diff --git a/frontend/src/api/apiEndpoints.ts b/frontend/src/api/apiEndpoints.ts index 805fc2010..4820c0408 100644 --- a/frontend/src/api/apiEndpoints.ts +++ b/frontend/src/api/apiEndpoints.ts @@ -5,6 +5,7 @@ export const imagesEndpoints = { export const faceClustersEndpoints = { getAllClusters: '/face-clusters/', searchForFaces: '/face-clusters/face-search', + searchForFacesBase64: '/face-clusters/face-search-base64', renameCluster: (clusterId: string) => `/face-clusters/${clusterId}`, getClusterImages: (clusterId: string) => `/face-clusters/${clusterId}/images`, }; diff --git a/frontend/src/components/Dialog/FaceSearchDialog.tsx b/frontend/src/components/Dialog/FaceSearchDialog.tsx index 16c88a670..00355a2a6 100644 --- a/frontend/src/components/Dialog/FaceSearchDialog.tsx +++ b/frontend/src/components/Dialog/FaceSearchDialog.tsx @@ -63,14 +63,15 @@ export function FaceSearchDialog() { const handleWebCam = async () => { try { await navigator.mediaDevices.getUserMedia({ video: true }); - - const devices = await navigator.mediaDevices.enumerateDevices(); - const videoInputs = devices.filter((d) => d.kind === 'videoinput'); - - console.log('Video Inputs:', videoInputs); } catch (err) { - console.error('Camera access denied:', err); - alert('Could not access camera: ' + err); + dispatch( + showInfoDialog({ + title: 'No Camera Found', + message: + 'No video input devices were detected. Please make sure a camera is connected and recognized by your system.', + variant: 'error', + }), + ); } }; From 4fba2f21df9e9816f7481b33bddaa60530939491 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 11:42:37 +0530 Subject: [PATCH 12/43] Fixed mutate function to fetch images from fetchSearchedFacesBase64 --- frontend/src/components/WebCam/WebCamComponent.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/WebCam/WebCamComponent.tsx b/frontend/src/components/WebCam/WebCamComponent.tsx index fa9057a78..3a13d289d 100644 --- a/frontend/src/components/WebCam/WebCamComponent.tsx +++ b/frontend/src/components/WebCam/WebCamComponent.tsx @@ -14,7 +14,7 @@ import { startSearch, setResults, clearSearch } from '@/features/searchSlice'; import type { Image } from '@/types/Media'; import { hideLoader, showLoader } from '@/features/loaderSlice'; import { usePictoMutation } from '@/hooks/useQueryExtension'; -import { fetchSearchedFaces } from '@/api/api-functions'; +import { fetchSearchedFacesBase64 } from '@/api/api-functions'; import { showInfoDialog } from '@/features/infoDialogSlice'; const videoConstraints = { @@ -32,8 +32,9 @@ function WebcamComponent({ isOpen, onClose }: WebcamComponentProps) { const webcamRef = useRef(null); const dispatch = useDispatch(); - const { mutate: getSearchImages } = usePictoMutation({ - mutationFn: async (path: string) => fetchSearchedFaces({ path }), + const { mutate: getSearchImagesBase64 } = usePictoMutation({ + mutationFn: async (base64_data: string) => + fetchSearchedFacesBase64({ base64_data }), onSuccess: (data) => { const result = data?.data as Image[]; dispatch(hideLoader()); @@ -81,7 +82,7 @@ function WebcamComponent({ isOpen, onClose }: WebcamComponentProps) { if (capturedImageUrl) { dispatch(startSearch(capturedImageUrl)); dispatch(showLoader('Searching faces...')); - getSearchImages(capturedImageUrl); + getSearchImagesBase64(capturedImageUrl); } }; From 14f55fc6043679361ebdfa631b10024689febc45 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Oct 2025 12:26:37 +0530 Subject: [PATCH 13/43] Fixed bugs in backend --- backend/app/routes/face_clusters.py | 3 +-- backend/app/schemas/images.py | 2 +- docs/backend/backend_python/openapi.json | 6 +++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/backend/app/routes/face_clusters.py b/backend/app/routes/face_clusters.py index 9bb607009..7ee5d677f 100644 --- a/backend/app/routes/face_clusters.py +++ b/backend/app/routes/face_clusters.py @@ -249,8 +249,7 @@ def face_tagging(payload: AddSingleImageRequest): @router.post("/face-search-base64") def face_search_base64(payload: AddSingleBase64ImageRequest): - base64_data = payload.base64 - + base64_data = payload.base64_data if not base64_data: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, diff --git a/backend/app/schemas/images.py b/backend/app/schemas/images.py index 3a9235403..1b6545531 100644 --- a/backend/app/schemas/images.py +++ b/backend/app/schemas/images.py @@ -8,7 +8,7 @@ class AddSingleImageRequest(BaseModel): class AddSingleBase64ImageRequest(BaseModel): - base64: str + base64_data: str class AddMultipleImagesRequest(BaseModel): diff --git a/docs/backend/backend_python/openapi.json b/docs/backend/backend_python/openapi.json index 1a3476925..71407173d 100644 --- a/docs/backend/backend_python/openapi.json +++ b/docs/backend/backend_python/openapi.json @@ -1329,14 +1329,14 @@ }, "AddSingleBase64ImageRequest": { "properties": { - "base64": { + "base64_data": { "type": "string", - "title": "Base64" + "title": "Base64 Data" } }, "type": "object", "required": [ - "base64" + "base64_data" ], "title": "AddSingleBase64ImageRequest" }, From efe79dbfb76d5951f056af38525300b1d184e4ce Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Oct 2025 12:27:08 +0530 Subject: [PATCH 14/43] Fixed frontend --- frontend/src/api/api-functions/face_clusters.ts | 1 + frontend/src/components/Dialog/FaceSearchDialog.tsx | 3 +++ frontend/src/components/WebCam/WebCamComponent.tsx | 1 + 3 files changed, 5 insertions(+) diff --git a/frontend/src/api/api-functions/face_clusters.ts b/frontend/src/api/api-functions/face_clusters.ts index 14268c16a..4e27af374 100644 --- a/frontend/src/api/api-functions/face_clusters.ts +++ b/frontend/src/api/api-functions/face_clusters.ts @@ -58,6 +58,7 @@ export const fetchSearchedFaces = async ( export const fetchSearchedFacesBase64 = async ( request: FetchSearchedFacesBase64Request, ): Promise => { + console.log(request) const response = await apiClient.post( faceClustersEndpoints.searchForFacesBase64, request, diff --git a/frontend/src/components/Dialog/FaceSearchDialog.tsx b/frontend/src/components/Dialog/FaceSearchDialog.tsx index 2a3a878fa..61fcf298a 100644 --- a/frontend/src/components/Dialog/FaceSearchDialog.tsx +++ b/frontend/src/components/Dialog/FaceSearchDialog.tsx @@ -63,7 +63,10 @@ export function FaceSearchDialog() { navigate(`/${ROUTES.HOME}`); try { await navigator.mediaDevices.getUserMedia({ video: true }); + setIsDialogOpen(false); + setShowCamera(true); } catch (error) { + setIsDialogOpen(false); dispatch( showInfoDialog({ title: "Webcam doesn't support", diff --git a/frontend/src/components/WebCam/WebCamComponent.tsx b/frontend/src/components/WebCam/WebCamComponent.tsx index 3a13d289d..af35b6323 100644 --- a/frontend/src/components/WebCam/WebCamComponent.tsx +++ b/frontend/src/components/WebCam/WebCamComponent.tsx @@ -80,6 +80,7 @@ function WebcamComponent({ isOpen, onClose }: WebcamComponentProps) { const handleSearchCapturedImage = () => { if (capturedImageUrl) { + handleClose() dispatch(startSearch(capturedImageUrl)); dispatch(showLoader('Searching faces...')); getSearchImagesBase64(capturedImageUrl); From fd18420877514c886cddf08d679e7440caf304c0 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 12:47:46 +0530 Subject: [PATCH 15/43] Fixed linting --- frontend/src/api/api-functions/face_clusters.ts | 2 +- frontend/src/components/WebCam/WebCamComponent.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/api/api-functions/face_clusters.ts b/frontend/src/api/api-functions/face_clusters.ts index 4e27af374..ac474e370 100644 --- a/frontend/src/api/api-functions/face_clusters.ts +++ b/frontend/src/api/api-functions/face_clusters.ts @@ -58,7 +58,7 @@ export const fetchSearchedFaces = async ( export const fetchSearchedFacesBase64 = async ( request: FetchSearchedFacesBase64Request, ): Promise => { - console.log(request) + console.log(request); const response = await apiClient.post( faceClustersEndpoints.searchForFacesBase64, request, diff --git a/frontend/src/components/WebCam/WebCamComponent.tsx b/frontend/src/components/WebCam/WebCamComponent.tsx index af35b6323..58505abd3 100644 --- a/frontend/src/components/WebCam/WebCamComponent.tsx +++ b/frontend/src/components/WebCam/WebCamComponent.tsx @@ -80,7 +80,7 @@ function WebcamComponent({ isOpen, onClose }: WebcamComponentProps) { const handleSearchCapturedImage = () => { if (capturedImageUrl) { - handleClose() + handleClose(); dispatch(startSearch(capturedImageUrl)); dispatch(showLoader('Searching faces...')); getSearchImagesBase64(capturedImageUrl); From dbc08201ae5f686fb5bee012c878c5538aca06d3 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 12:56:54 +0530 Subject: [PATCH 16/43] Removed redundant import --- frontend/src-tauri/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src-tauri/src/main.rs b/frontend/src-tauri/src/main.rs index 0fe70bd55..396358bf8 100644 --- a/frontend/src-tauri/src/main.rs +++ b/frontend/src-tauri/src/main.rs @@ -4,7 +4,7 @@ mod services; use tauri::path::BaseDirectory; -use tauri::{Manager, WebviewWindowBuilder}; +use tauri::Manager; fn main() { tauri::Builder::default() From 5b216a6b5ca8b213e5574fa911951bad88ab7f2e Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 12:58:11 +0530 Subject: [PATCH 17/43] Reverted main.rs file --- frontend/src-tauri/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src-tauri/src/main.rs b/frontend/src-tauri/src/main.rs index 396358bf8..b46b886ea 100644 --- a/frontend/src-tauri/src/main.rs +++ b/frontend/src-tauri/src/main.rs @@ -21,6 +21,7 @@ fn main() { println!("Resource path: {:?}", resource_path); Ok(()) }) + .invoke_handler(tauri::generate_handler![services::get_server_path,]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } From 1f7113da4019a7bf7749b7b70e48f5536565545b Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 12:59:43 +0530 Subject: [PATCH 18/43] Reverted files --- frontend/src-tauri/Cargo.lock | 2 +- frontend/src-tauri/tauri.conf.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src-tauri/Cargo.lock b/frontend/src-tauri/Cargo.lock index eb41c4c68..26d7bfc77 100644 --- a/frontend/src-tauri/Cargo.lock +++ b/frontend/src-tauri/Cargo.lock @@ -723,7 +723,7 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.0", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] diff --git a/frontend/src-tauri/tauri.conf.json b/frontend/src-tauri/tauri.conf.json index b2a3ac46e..86bfa0113 100644 --- a/frontend/src-tauri/tauri.conf.json +++ b/frontend/src-tauri/tauri.conf.json @@ -62,7 +62,7 @@ "scope": ["**"], "enable": true }, - "csp": "default-src 'self' ipc: http://ipc.localhost; img-src 'self' data: asset: http://asset.localhost; connect-src 'self' http://localhost:8000 ws://localhost:8000 http://localhost:8001 ws://localhost:8001" + "csp": "default-src 'self' ipc: http://ipc.localhost; img-src 'self' data: asset: http://asset.localhost; connect-src 'self' http://localhost:8000 ws://localhost:8000 http://localhost:8001 ws://localhost:8001" } } } From eb99b0e23b2a0c1472ad703b9d8530b36ed8d0b3 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 13:04:44 +0530 Subject: [PATCH 19/43] Fixed bugs --- backend/app/routes/face_clusters.py | 29 ++----------------- .../src/api/api-functions/face_clusters.ts | 1 - 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/backend/app/routes/face_clusters.py b/backend/app/routes/face_clusters.py index 7ee5d677f..49b2b3fc9 100644 --- a/backend/app/routes/face_clusters.py +++ b/backend/app/routes/face_clusters.py @@ -27,30 +27,6 @@ from app.utils.faceSearch import perform_face_search -class BoundingBox(BaseModel): - x: float - y: float - width: float - height: float - - -class ImageData(BaseModel): - id: str - path: str - folder_id: str - thumbnailPath: str - metadata: Dict[str, Any] - isTagged: bool - tags: Optional[List[str]] = None - bboxes: BoundingBox - - -class GetAllImagesResponse(BaseModel): - success: bool - message: str - data: List[ImageData] - - logger = logging.getLogger(__name__) router = APIRouter() @@ -249,7 +225,7 @@ def face_tagging(payload: AddSingleImageRequest): @router.post("/face-search-base64") def face_search_base64(payload: AddSingleBase64ImageRequest): - base64_data = payload.base64_data + base64_data = payload.base64_data if not base64_data: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -260,6 +236,7 @@ def face_search_base64(payload: AddSingleBase64ImageRequest): ).model_dump(), ) + image_path = None try: image_bytes = base64.b64decode(base64_data.split(",")[-1]) image_id = str(uuid.uuid4())[:8] @@ -274,5 +251,5 @@ def face_search_base64(payload: AddSingleBase64ImageRequest): return result finally: - if os.path.exists(image_path): + if image_path and os.path.exists(image_path): os.remove(image_path) diff --git a/frontend/src/api/api-functions/face_clusters.ts b/frontend/src/api/api-functions/face_clusters.ts index ac474e370..14268c16a 100644 --- a/frontend/src/api/api-functions/face_clusters.ts +++ b/frontend/src/api/api-functions/face_clusters.ts @@ -58,7 +58,6 @@ export const fetchSearchedFaces = async ( export const fetchSearchedFacesBase64 = async ( request: FetchSearchedFacesBase64Request, ): Promise => { - console.log(request); const response = await apiClient.post( faceClustersEndpoints.searchForFacesBase64, request, From 7c8bef71647673f3172148040c84f5cab4db526a Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 15:43:06 +0530 Subject: [PATCH 20/43] Fixed grammatical mistake --- frontend/src/components/Dialog/FaceSearchDialog.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/Dialog/FaceSearchDialog.tsx b/frontend/src/components/Dialog/FaceSearchDialog.tsx index 61fcf298a..b11b72281 100644 --- a/frontend/src/components/Dialog/FaceSearchDialog.tsx +++ b/frontend/src/components/Dialog/FaceSearchDialog.tsx @@ -69,7 +69,7 @@ export function FaceSearchDialog() { setIsDialogOpen(false); dispatch( showInfoDialog({ - title: "Webcam doesn't support", + title: 'Webcam Not Supported', message: 'Webcam is not supported or access was denied on this device.', variant: 'error', From 7297b59587e5ebd4128b7c2312eb1cb4b349a482 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 18:32:03 +0530 Subject: [PATCH 21/43] Fixed critical and major bugs --- backend/app/routes/face_clusters.py | 15 ++++++++++++--- backend/app/utils/faceSearch.py | 9 ++++++++- frontend/src-tauri/tauri.conf.json | 7 +++++-- .../src/components/Dialog/FaceSearchDialog.tsx | 4 +++- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/backend/app/routes/face_clusters.py b/backend/app/routes/face_clusters.py index 49b2b3fc9..c10ef8b6a 100644 --- a/backend/app/routes/face_clusters.py +++ b/backend/app/routes/face_clusters.py @@ -1,9 +1,8 @@ import logging +from binascii import Error as Base64Error import base64 import uuid import os -from typing import Optional, List, Dict, Any -from pydantic import BaseModel from fastapi import APIRouter, HTTPException, status from app.database.face_clusters import ( db_get_cluster_by_id, @@ -238,7 +237,17 @@ def face_search_base64(payload: AddSingleBase64ImageRequest): image_path = None try: - image_bytes = base64.b64decode(base64_data.split(",")[-1]) + try: + image_bytes = base64.b64decode(base64_data.split(",")[-1]) + except (Base64Error, ValueError): + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ErrorResponse( + success=False, + error="Invalid base64 data", + message="The provided base64 image data is malformed or invalid.", + ).model_dump(), + ) image_id = str(uuid.uuid4())[:8] temp_dir = "temp_uploads" os.makedirs(temp_dir, exist_ok=True) diff --git a/backend/app/utils/faceSearch.py b/backend/app/utils/faceSearch.py index 10321610a..1c4abbef2 100644 --- a/backend/app/utils/faceSearch.py +++ b/backend/app/utils/faceSearch.py @@ -49,7 +49,14 @@ def perform_face_search(image_path: str) -> GetAllImagesResponse: matches = [] image_id = str(uuid.uuid4()) - result = fd.detect_faces(image_id, image_path, forSearch=True) + try: + result = fd.detect_faces(image_id, image_path, forSearch=True) + except Exception as e: + return GetAllImagesResponse( + success=False, + message=f"Failed to process image: {str(e)}", + data=[], + ) if not result or result["num_faces"] == 0: return GetAllImagesResponse( success=True, diff --git a/frontend/src-tauri/tauri.conf.json b/frontend/src-tauri/tauri.conf.json index 86bfa0113..4c9dd3e1f 100644 --- a/frontend/src-tauri/tauri.conf.json +++ b/frontend/src-tauri/tauri.conf.json @@ -26,7 +26,10 @@ "../../sync-microservice/dist/": "resources/sync-microservice" }, "macOS": { - "signingIdentity": "-" + "signingIdentity": "-", + "infoPlist": { + "NSCameraUsageDescription": "PictoPy needs camera access to capture images from your webcam." + } } }, "productName": "PictoPy", @@ -62,7 +65,7 @@ "scope": ["**"], "enable": true }, - "csp": "default-src 'self' ipc: http://ipc.localhost; img-src 'self' data: asset: http://asset.localhost; connect-src 'self' http://localhost:8000 ws://localhost:8000 http://localhost:8001 ws://localhost:8001" + "csp": "default-src 'self'; img-src 'self' data: asset: http://asset.localhost; media-src 'self' blob: data:; connect-src 'self' ipc: http://ipc.localhost http://localhost:8000 ws://localhost:8000 http://localhost:8001 ws://localhost:8001" } } } diff --git a/frontend/src/components/Dialog/FaceSearchDialog.tsx b/frontend/src/components/Dialog/FaceSearchDialog.tsx index b11b72281..f9c9f5433 100644 --- a/frontend/src/components/Dialog/FaceSearchDialog.tsx +++ b/frontend/src/components/Dialog/FaceSearchDialog.tsx @@ -63,6 +63,9 @@ export function FaceSearchDialog() { navigate(`/${ROUTES.HOME}`); try { await navigator.mediaDevices.getUserMedia({ video: true }); + const stream = await navigator.mediaDevices.getUserMedia({ video: true }); + stream.getTracks().forEach((track) => track.stop()); + navigate(`/${ROUTES.HOME}`); setIsDialogOpen(false); setShowCamera(true); } catch (error) { @@ -77,7 +80,6 @@ export function FaceSearchDialog() { ); } }; - const handlePickFile = async () => { navigate(`/${ROUTES.HOME}`); const filePath = await pickSingleFile(); From a12a7c921c4b9be24237a05101b68f07f7d1f999 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 18:35:11 +0530 Subject: [PATCH 22/43] Fixed tauri config file --- frontend/src-tauri/tauri.conf.json | 5 +- package-lock.json | 978 +++++++++++++++++++++++++++++ package.json | 5 +- 3 files changed, 983 insertions(+), 5 deletions(-) diff --git a/frontend/src-tauri/tauri.conf.json b/frontend/src-tauri/tauri.conf.json index 4c9dd3e1f..d02b00e91 100644 --- a/frontend/src-tauri/tauri.conf.json +++ b/frontend/src-tauri/tauri.conf.json @@ -26,10 +26,7 @@ "../../sync-microservice/dist/": "resources/sync-microservice" }, "macOS": { - "signingIdentity": "-", - "infoPlist": { - "NSCameraUsageDescription": "PictoPy needs camera access to capture images from your webcam." - } + "signingIdentity": "-" } }, "productName": "PictoPy", diff --git a/package-lock.json b/package-lock.json index 859690e68..9cf80f01f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,10 +7,624 @@ "": { "name": "pictopy", "version": "0.0.0", + "dependencies": { + "eslint": "^9.37.0" + }, "devDependencies": { "husky": "^9.1.7" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz", + "integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", + "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.37.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.37.0.tgz", + "integrity": "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz", + "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==", + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.37.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz", + "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.4.0", + "@eslint/core": "^0.16.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.37.0", + "@eslint/plugin-kit": "^0.4.0", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "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.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "license": "ISC" + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/husky": { "version": "9.1.7", "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", @@ -26,6 +640,370 @@ "funding": { "url": "https://github.com/sponsors/typicode" } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index c298b862e..70b722b52 100644 --- a/package.json +++ b/package.json @@ -16,5 +16,8 @@ }, "devDependencies": { "husky": "^9.1.7" + }, + "dependencies": { + "eslint": "^9.37.0" } -} \ No newline at end of file +} From 340b1e9e4ed018b59791a95da1cc21d1e2888bfb Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 18:38:05 +0530 Subject: [PATCH 23/43] Fixed package json --- package-lock.json | 978 ---------------------------------------------- package.json | 3 - 2 files changed, 981 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9cf80f01f..859690e68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,624 +7,10 @@ "": { "name": "pictopy", "version": "0.0.0", - "dependencies": { - "eslint": "^9.37.0" - }, "devDependencies": { "husky": "^9.1.7" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz", - "integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==", - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.16.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", - "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "9.37.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.37.0.tgz", - "integrity": "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==", - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz", - "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==", - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.16.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.4.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "license": "MIT" - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.37.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz", - "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.4.0", - "@eslint/core": "^0.16.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.37.0", - "@eslint/plugin-kit": "^0.4.0", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "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.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "license": "MIT" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "license": "MIT" - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "license": "ISC" - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/husky": { "version": "9.1.7", "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", @@ -640,370 +26,6 @@ "funding": { "url": "https://github.com/sponsors/typicode" } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "license": "MIT" - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "license": "MIT" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "license": "MIT" - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } } } } diff --git a/package.json b/package.json index 70b722b52..61a8a383a 100644 --- a/package.json +++ b/package.json @@ -16,8 +16,5 @@ }, "devDependencies": { "husky": "^9.1.7" - }, - "dependencies": { - "eslint": "^9.37.0" } } From aed41b4e1a4d0f621d4a3dc6da5741673bd937e3 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 18:43:43 +0530 Subject: [PATCH 24/43] Reformated using black --- backend/app/database/face_clusters.py | 6 +++--- backend/app/database/faces.py | 8 ++++---- backend/app/database/folders.py | 6 +++--- backend/app/routes/albums.py | 1 + backend/app/utils/faceSearch.py | 4 +++- backend/app/utils/images.py | 4 ++-- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/backend/app/database/face_clusters.py b/backend/app/database/face_clusters.py index 5bfa956e2..f014e9be7 100644 --- a/backend/app/database/face_clusters.py +++ b/backend/app/database/face_clusters.py @@ -195,9 +195,9 @@ def db_delete_all_clusters() -> int: return deleted_count -def db_get_all_clusters_with_face_counts() -> List[ - Dict[str, Union[str, Optional[str], int]] -]: +def db_get_all_clusters_with_face_counts() -> ( + List[Dict[str, Union[str, Optional[str], int]]] +): """ Retrieve all clusters with their face counts and stored face images. diff --git a/backend/app/database/faces.py b/backend/app/database/faces.py index 9a8a0269a..e5019f180 100644 --- a/backend/app/database/faces.py +++ b/backend/app/database/faces.py @@ -234,9 +234,9 @@ def db_get_faces_unassigned_clusters() -> List[Dict[str, Union[FaceId, FaceEmbed return faces -def db_get_all_faces_with_cluster_names() -> List[ - Dict[str, Union[FaceId, FaceEmbedding, Optional[str]]] -]: +def db_get_all_faces_with_cluster_names() -> ( + List[Dict[str, Union[FaceId, FaceEmbedding, Optional[str]]]] +): """ Get all faces with their corresponding cluster names. @@ -271,7 +271,7 @@ def db_get_all_faces_with_cluster_names() -> List[ def db_update_face_cluster_ids_batch( - face_cluster_mapping: List[Dict[str, Union[FaceId, ClusterId]]] + face_cluster_mapping: List[Dict[str, Union[FaceId, ClusterId]]], ) -> None: """ Update cluster IDs for multiple faces in batch. diff --git a/backend/app/database/folders.py b/backend/app/database/folders.py index 383628d1c..d9407eb12 100644 --- a/backend/app/database/folders.py +++ b/backend/app/database/folders.py @@ -382,9 +382,9 @@ def db_get_folder_ids_by_paths( conn.close() -def db_get_all_folder_details() -> List[ - Tuple[str, str, Optional[str], int, bool, Optional[bool]] -]: +def db_get_all_folder_details() -> ( + List[Tuple[str, str, Optional[str], int, bool, Optional[bool]]] +): """ Get all folder details including folder_id, folder_path, parent_folder_id, last_modified_time, AI_Tagging, and taggingCompleted. diff --git a/backend/app/routes/albums.py b/backend/app/routes/albums.py index 5126b81c5..ae0408613 100644 --- a/backend/app/routes/albums.py +++ b/backend/app/routes/albums.py @@ -29,6 +29,7 @@ router = APIRouter() + # GET /albums/ - Get all albums @router.get("/", response_model=GetAlbumsResponse) def get_albums(show_hidden: bool = Query(False)): diff --git a/backend/app/utils/faceSearch.py b/backend/app/utils/faceSearch.py index 1c4abbef2..82bf42f1d 100644 --- a/backend/app/utils/faceSearch.py +++ b/backend/app/utils/faceSearch.py @@ -76,7 +76,9 @@ def perform_face_search(image_path: str) -> GetAllImagesResponse: ) for image in images: - similarity = FaceNet_util_cosine_similarity(new_embedding, image["embeddings"]) + similarity = FaceNet_util_cosine_similarity( + new_embedding, image["embeddings"] + ) if similarity >= CONFIDENCE_PERCENT: matches.append( ImageData( diff --git a/backend/app/utils/images.py b/backend/app/utils/images.py index fab19ef5b..d31b38184 100644 --- a/backend/app/utils/images.py +++ b/backend/app/utils/images.py @@ -99,7 +99,7 @@ def image_util_process_untagged_images() -> bool: def image_util_classify_and_face_detect_images( - untagged_images: List[Dict[str, str]] + untagged_images: List[Dict[str, str]], ) -> None: """Classify untagged images and detect faces if applicable.""" object_classifier = ObjectClassifier() @@ -262,7 +262,7 @@ def image_util_remove_obsolete_images(folder_id_list: List[int]) -> int: def image_util_create_folder_path_mapping( - folder_ids: List[Tuple[int, str]] + folder_ids: List[Tuple[int, str]], ) -> Dict[str, int]: """ Create a dictionary mapping folder paths to their IDs. From aa0149064d8bfe7e898f7ff8c3af94ea6b437dc5 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 18:49:18 +0530 Subject: [PATCH 25/43] Fixed webcam bugs --- frontend/src/components/Dialog/FaceSearchDialog.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontend/src/components/Dialog/FaceSearchDialog.tsx b/frontend/src/components/Dialog/FaceSearchDialog.tsx index f9c9f5433..217d73f37 100644 --- a/frontend/src/components/Dialog/FaceSearchDialog.tsx +++ b/frontend/src/components/Dialog/FaceSearchDialog.tsx @@ -60,16 +60,13 @@ export function FaceSearchDialog() { }, }); const handleWebCam = async () => { - navigate(`/${ROUTES.HOME}`); try { - await navigator.mediaDevices.getUserMedia({ video: true }); const stream = await navigator.mediaDevices.getUserMedia({ video: true }); stream.getTracks().forEach((track) => track.stop()); navigate(`/${ROUTES.HOME}`); setIsDialogOpen(false); setShowCamera(true); } catch (error) { - setIsDialogOpen(false); dispatch( showInfoDialog({ title: 'Webcam Not Supported', From 8967c0331be0361a67300db2743aab84e63f1c3c Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Thu, 16 Oct 2025 18:51:09 +0530 Subject: [PATCH 26/43] Fixed cleanup --- backend/app/utils/faceSearch.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/app/utils/faceSearch.py b/backend/app/utils/faceSearch.py index 82bf42f1d..385cce908 100644 --- a/backend/app/utils/faceSearch.py +++ b/backend/app/utils/faceSearch.py @@ -100,5 +100,7 @@ def perform_face_search(image_path: str) -> GetAllImagesResponse: ) finally: - fd.close() - fn.close() + if "fd" in locals() and fd is not None: + fd.close() + if "fn" in locals() and fn is not None: + fn.close() From e74e37e1c453e58ccc543bde01fcf4481d0f7c23 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Sun, 19 Oct 2025 11:01:57 +0530 Subject: [PATCH 27/43] Fixed default image to appear when searching --- frontend/public/photo.jpeg | Bin 0 -> 1670 bytes .../src/components/Navigation/Navbar/Navbar.tsx | 2 +- .../src/components/WebCam/WebCamComponent.tsx | 12 ++++++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 frontend/public/photo.jpeg diff --git a/frontend/public/photo.jpeg b/frontend/public/photo.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..8b39d3493c40ed642ff9219b10515110bad3d2f3 GIT binary patch literal 1670 zcmb7Be>l^59RF?$+sv_M^@QbDQhxNDW62!5vQc8pew~Dfqe(KSb)$1p?vTp-NR||t z3|lIzg$_-u{65_f(GR~;c+~PUJMQY9dfe0V-23y#`~7*pp7-nZdOvSvmvR8ma&_M2 z41hoY09ty0@-c7%fT^lM)l^|nH7FboQ`cCdsewRf=xU?2))-)nj0`aP`WrUcSZvs6 zWvZ`l>0oJvwZ-9Z#^!heew&kx9nKa6hr=}x8akSqI<_YICbs`Olr;bn3Y-EOAs{0F zj08cDAf*)0TehgOZ1vxOf>x=hs(~R(C{7CiLBL=Y*eW>W0}cX1mSCjXYOC#Jw4sqP zH6Sv*-Rt<}T9o$MZ>)C&rj<{wVR4scwLc^MdwRKx{8Z|nZV!NffR-#lkN_SSH~1j* zg{0jCw`=TdrXf*G;XM~=4!!Q(I)8BI-Rp&U92|Yjm=RwYA|1x=}+e|PWgo= zX_?mdB^E;WGU7mJRs(6>2WiE7cV7HiJ?T3 zAJ$@SJR`=+Ep8z?VKs8&bQ>zwH<_nNh-(|-niiHOX!e_7EG-_K;$I{-2eMu^WB0JdNqKrgw5r)dnEIa`3J7AZ7$$t6*=bLS4_HGLI$@+^$Mdh z_m<=cCMb0HPlwu0MK{_Lzx>^GyjQ_iTEC04?!+XmNQTGrXdS?m<%QPh(F~ z$Em|s(xMLf>0+x)d!`|a(r0vt+*I7oiP>VzH>_h<*?W!%#j}BgZZoW}Zk67Jntio? z5s|!mU8L#X1iENJzs1$cV0y{^h?H~L>bueT{Ml%}xUJmZ!Kpo!&{xlppe|(7cORt3 z5HWZ1CX4eAhEK@0=3GquF?v_Rfj+V|H-FTe#SJ2*pt=v-4O+1X0DwE5v#y9Kj)JEY zv<-s9e(;tFVy8XZS&*45`(9o_F$qhzp`-^o*!6@y897L0$*b+S3`L|UQSm+%{*+(k zLsiUGWn`T4O+Br>w|cw@roM;|md}xPUY5VRTiUAx5{$LUQfZJ|m`)NGTg){?J3fjO zieqms%p5~GAPOtpkBT!#6-k@Tx_CYon|j~BZiHda+O607BbQ(PI&t2`5+Xkz9OA8W zbi$+S<<_xGla}+D^to)oK2DUQX~9|b71u$i+DJRQylTl&0%{bmJ<)Os&x&J%&NR$S z^(TZz4^eZ(gqNFhs>Ub$pw6X?lr1xS3G+||DTd6sy+`7rbC@uj#TaW2o*Q+z|J+RW zt&m3RO_HD_h$BphRZa!~A1VaUO|1cL-t4+ZG73`=rBm|fj=>f?RD4lW4Z8WeEDpXQ zYa!T41iykUFYpC%*9xxU)U-mTP${DviuGiy)4BdGD)ocTaw$J&mI| zOZwIo^y^L+O&?x2`Pr$!)}yT`+?(XQ@Z+-`KAftwpK?uy{EyTT{l>W6A!WB6I5usL zG!KQ_BH?SnRjz=)C+R|og@_?xa0EjFHR(sPQ4T`da^qQ+Psq>IbL&MWem}@&8U5FW ze(lN1ciodMFl32$UOW@XA0##dyi4WR873{QM8Eox&Kgcz(=CxjK!Ga=p&0$ zT{^=KlT0J5HLbZZrFnqp=PrCjbEH(mL|hH(z%M&afB36ylpit6+x+B&{1FL?rNo2a zc3UgUsk5ZFdOY7QL2MBRw7Op@mbwySxiJFAVGcD!)R;<&&u01Btz4Br3r3(}n)4 I#w)x30>?L#kN^Mx literal 0 HcmV?d00001 diff --git a/frontend/src/components/Navigation/Navbar/Navbar.tsx b/frontend/src/components/Navigation/Navbar/Navbar.tsx index 8a709dcbb..56e4d0714 100644 --- a/frontend/src/components/Navigation/Navbar/Navbar.tsx +++ b/frontend/src/components/Navigation/Navbar/Navbar.tsx @@ -34,7 +34,7 @@ export function Navbar() { {queryImage && (
Query diff --git a/frontend/src/components/WebCam/WebCamComponent.tsx b/frontend/src/components/WebCam/WebCamComponent.tsx index 58505abd3..d71cec346 100644 --- a/frontend/src/components/WebCam/WebCamComponent.tsx +++ b/frontend/src/components/WebCam/WebCamComponent.tsx @@ -79,16 +79,24 @@ function WebcamComponent({ isOpen, onClose }: WebcamComponentProps) { }; const handleSearchCapturedImage = () => { + handleClose(); if (capturedImageUrl) { - handleClose(); dispatch(startSearch(capturedImageUrl)); dispatch(showLoader('Searching faces...')); getSearchImagesBase64(capturedImageUrl); + } else { + dispatch( + showInfoDialog({ + title: 'Capture Failed', + message: 'An unexpected error occurred during capture.', + variant: 'error', + }), + ); } }; const handleClose = () => { - setShowCamera(true); + setShowCamera(false); setCapturedImageUrl(null); onClose(); }; From 06f3c53548bbff8d7c1029cee21837fe280f442a Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 19 Oct 2025 11:37:19 +0530 Subject: [PATCH 28/43] Fixed thumbnail image and webcam onclose --- frontend/src/components/Navigation/Navbar/Navbar.tsx | 2 +- frontend/src/components/WebCam/WebCamComponent.tsx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/Navigation/Navbar/Navbar.tsx b/frontend/src/components/Navigation/Navbar/Navbar.tsx index 56e4d0714..971c244ea 100644 --- a/frontend/src/components/Navigation/Navbar/Navbar.tsx +++ b/frontend/src/components/Navigation/Navbar/Navbar.tsx @@ -34,7 +34,7 @@ export function Navbar() { {queryImage && (
Query diff --git a/frontend/src/components/WebCam/WebCamComponent.tsx b/frontend/src/components/WebCam/WebCamComponent.tsx index d71cec346..65c43295f 100644 --- a/frontend/src/components/WebCam/WebCamComponent.tsx +++ b/frontend/src/components/WebCam/WebCamComponent.tsx @@ -55,6 +55,7 @@ function WebcamComponent({ isOpen, onClose }: WebcamComponentProps) { }, onError: () => { dispatch(hideLoader()); + handleClose(); dispatch( showInfoDialog({ title: 'Search Failed', @@ -79,7 +80,7 @@ function WebcamComponent({ isOpen, onClose }: WebcamComponentProps) { }; const handleSearchCapturedImage = () => { - handleClose(); + onClose(); if (capturedImageUrl) { dispatch(startSearch(capturedImageUrl)); dispatch(showLoader('Searching faces...')); @@ -92,11 +93,12 @@ function WebcamComponent({ isOpen, onClose }: WebcamComponentProps) { variant: 'error', }), ); + handleClose(); } }; const handleClose = () => { - setShowCamera(false); + setShowCamera(true); setCapturedImageUrl(null); onClose(); }; From 66b22a5fb0b343fe396b96d689d0b282b356cb53 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Sun, 19 Oct 2025 12:00:51 +0530 Subject: [PATCH 29/43] Fixed merge conflicts --- .../components/Dialog/FaceSearchDialog.tsx | 104 +++++++++--------- 1 file changed, 50 insertions(+), 54 deletions(-) diff --git a/frontend/src/components/Dialog/FaceSearchDialog.tsx b/frontend/src/components/Dialog/FaceSearchDialog.tsx index 217d73f37..4d13a9c38 100644 --- a/frontend/src/components/Dialog/FaceSearchDialog.tsx +++ b/frontend/src/components/Dialog/FaceSearchDialog.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Upload, Camera, ScanFace } from 'lucide-react'; +import { Camera, ScanFace } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Dialog, @@ -88,67 +88,63 @@ export function FaceSearchDialog() { } }; return ( - <> - - + + + + + + + + Face Detection Search + + Search for images containing specific faces by uploading a photo or + using your webcam. + + + +
+ {/* Upload Button */} - - - - Face Detection Search - - Search for images containing specific faces by uploading a photo - or using your webcam. - - - -
- - - -
-

- PictoPy will analyze the face and find matching images in your - gallery. -

-
-
+ {/* Webcam Button */} + +
+ setShowCamera(false)} /> - + ); } From 7c3eeb0cd8d795b96b76452ddcdb0595c278a613 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Sun, 19 Oct 2025 12:01:33 +0530 Subject: [PATCH 30/43] Fixed linting --- frontend/src/components/Navigation/Navbar/Navbar.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Navigation/Navbar/Navbar.tsx b/frontend/src/components/Navigation/Navbar/Navbar.tsx index 971c244ea..20f70449f 100644 --- a/frontend/src/components/Navigation/Navbar/Navbar.tsx +++ b/frontend/src/components/Navigation/Navbar/Navbar.tsx @@ -34,7 +34,11 @@ export function Navbar() { {queryImage && (
Query From f7c4a9711e0429b1d79dc6d5030f7e89766ed0f2 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Sun, 19 Oct 2025 12:07:33 +0530 Subject: [PATCH 31/43] Removed duplicate photo.jpeg --- frontend/public/photo.jpeg | Bin 1670 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 frontend/public/photo.jpeg diff --git a/frontend/public/photo.jpeg b/frontend/public/photo.jpeg deleted file mode 100644 index 8b39d3493c40ed642ff9219b10515110bad3d2f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1670 zcmb7Be>l^59RF?$+sv_M^@QbDQhxNDW62!5vQc8pew~Dfqe(KSb)$1p?vTp-NR||t z3|lIzg$_-u{65_f(GR~;c+~PUJMQY9dfe0V-23y#`~7*pp7-nZdOvSvmvR8ma&_M2 z41hoY09ty0@-c7%fT^lM)l^|nH7FboQ`cCdsewRf=xU?2))-)nj0`aP`WrUcSZvs6 zWvZ`l>0oJvwZ-9Z#^!heew&kx9nKa6hr=}x8akSqI<_YICbs`Olr;bn3Y-EOAs{0F zj08cDAf*)0TehgOZ1vxOf>x=hs(~R(C{7CiLBL=Y*eW>W0}cX1mSCjXYOC#Jw4sqP zH6Sv*-Rt<}T9o$MZ>)C&rj<{wVR4scwLc^MdwRKx{8Z|nZV!NffR-#lkN_SSH~1j* zg{0jCw`=TdrXf*G;XM~=4!!Q(I)8BI-Rp&U92|Yjm=RwYA|1x=}+e|PWgo= zX_?mdB^E;WGU7mJRs(6>2WiE7cV7HiJ?T3 zAJ$@SJR`=+Ep8z?VKs8&bQ>zwH<_nNh-(|-niiHOX!e_7EG-_K;$I{-2eMu^WB0JdNqKrgw5r)dnEIa`3J7AZ7$$t6*=bLS4_HGLI$@+^$Mdh z_m<=cCMb0HPlwu0MK{_Lzx>^GyjQ_iTEC04?!+XmNQTGrXdS?m<%QPh(F~ z$Em|s(xMLf>0+x)d!`|a(r0vt+*I7oiP>VzH>_h<*?W!%#j}BgZZoW}Zk67Jntio? z5s|!mU8L#X1iENJzs1$cV0y{^h?H~L>bueT{Ml%}xUJmZ!Kpo!&{xlppe|(7cORt3 z5HWZ1CX4eAhEK@0=3GquF?v_Rfj+V|H-FTe#SJ2*pt=v-4O+1X0DwE5v#y9Kj)JEY zv<-s9e(;tFVy8XZS&*45`(9o_F$qhzp`-^o*!6@y897L0$*b+S3`L|UQSm+%{*+(k zLsiUGWn`T4O+Br>w|cw@roM;|md}xPUY5VRTiUAx5{$LUQfZJ|m`)NGTg){?J3fjO zieqms%p5~GAPOtpkBT!#6-k@Tx_CYon|j~BZiHda+O607BbQ(PI&t2`5+Xkz9OA8W zbi$+S<<_xGla}+D^to)oK2DUQX~9|b71u$i+DJRQylTl&0%{bmJ<)Os&x&J%&NR$S z^(TZz4^eZ(gqNFhs>Ub$pw6X?lr1xS3G+||DTd6sy+`7rbC@uj#TaW2o*Q+z|J+RW zt&m3RO_HD_h$BphRZa!~A1VaUO|1cL-t4+ZG73`=rBm|fj=>f?RD4lW4Z8WeEDpXQ zYa!T41iykUFYpC%*9xxU)U-mTP${DviuGiy)4BdGD)ocTaw$J&mI| zOZwIo^y^L+O&?x2`Pr$!)}yT`+?(XQ@Z+-`KAftwpK?uy{EyTT{l>W6A!WB6I5usL zG!KQ_BH?SnRjz=)C+R|og@_?xa0EjFHR(sPQ4T`da^qQ+Psq>IbL&MWem}@&8U5FW ze(lN1ciodMFl32$UOW@XA0##dyi4WR873{QM8Eox&Kgcz(=CxjK!Ga=p&0$ zT{^=KlT0J5HLbZZrFnqp=PrCjbEH(mL|hH(z%M&afB36ylpit6+x+B&{1FL?rNo2a zc3UgUsk5ZFdOY7QL2MBRw7Op@mbwySxiJFAVGcD!)R;<&&u01Btz4Br3r3(}n)4 I#w)x30>?L#kN^Mx From ac41b8b10ada02da937c7f9f4fbf19c97ee21019 Mon Sep 17 00:00:00 2001 From: tushar1977 Date: Sun, 19 Oct 2025 12:18:01 +0530 Subject: [PATCH 32/43] Fixing major bugs --- .../components/Dialog/FaceSearchDialog.tsx | 100 +++++++++--------- .../src/components/WebCam/WebCamComponent.tsx | 11 +- 2 files changed, 58 insertions(+), 53 deletions(-) diff --git a/frontend/src/components/Dialog/FaceSearchDialog.tsx b/frontend/src/components/Dialog/FaceSearchDialog.tsx index 4d13a9c38..3a9d6d667 100644 --- a/frontend/src/components/Dialog/FaceSearchDialog.tsx +++ b/frontend/src/components/Dialog/FaceSearchDialog.tsx @@ -88,63 +88,65 @@ export function FaceSearchDialog() { } }; return ( - - - - - - - - Face Detection Search - - Search for images containing specific faces by uploading a photo or - using your webcam. - - - -
- {/* Upload Button */} + <> + + + - {/* Webcam Button */} - -
-
+ + + Face Detection Search + + Search for images containing specific faces by uploading a photo + or using your webcam. + + + +
+ {/* Upload Button */} + + + {/* Webcam Button */} + +
+
+
setShowCamera(false)} /> - + ); } diff --git a/frontend/src/components/WebCam/WebCamComponent.tsx b/frontend/src/components/WebCam/WebCamComponent.tsx index 65c43295f..6e652d700 100644 --- a/frontend/src/components/WebCam/WebCamComponent.tsx +++ b/frontend/src/components/WebCam/WebCamComponent.tsx @@ -104,7 +104,12 @@ function WebcamComponent({ isOpen, onClose }: WebcamComponentProps) { }; return ( - + { + if (!open) handleClose(); + }} + > @@ -122,12 +127,10 @@ function WebcamComponent({ isOpen, onClose }: WebcamComponentProps) {