Add biometric authentication enrollment UI
- Create biometric API client with WebAuthn methods - Add BiometricSettings component for credential management - Support Face ID, Touch ID, Windows Hello enrollment - Display list of enrolled credentials with metadata - Add/remove/rename biometric credentials - Check browser and platform authenticator support - Integrate into settings page with animations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import { usersApi } from '@/lib/api/users';
|
|||||||
import { MFASettings } from '@/components/settings/MFASettings';
|
import { MFASettings } from '@/components/settings/MFASettings';
|
||||||
import { SessionsManagement } from '@/components/settings/SessionsManagement';
|
import { SessionsManagement } from '@/components/settings/SessionsManagement';
|
||||||
import { DeviceTrustManagement } from '@/components/settings/DeviceTrustManagement';
|
import { DeviceTrustManagement } from '@/components/settings/DeviceTrustManagement';
|
||||||
|
import { BiometricSettings } from '@/components/settings/BiometricSettings';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
export default function SettingsPage() {
|
export default function SettingsPage() {
|
||||||
@@ -253,6 +254,17 @@ export default function SettingsPage() {
|
|||||||
</Box>
|
</Box>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Biometric Authentication */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.4, delay: 0.36 }}
|
||||||
|
>
|
||||||
|
<Box sx={{ mb: 3 }}>
|
||||||
|
<BiometricSettings />
|
||||||
|
</Box>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
{/* Account Actions */}
|
{/* Account Actions */}
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
|||||||
406
maternal-web/components/settings/BiometricSettings.tsx
Normal file
406
maternal-web/components/settings/BiometricSettings.tsx
Normal file
@@ -0,0 +1,406 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Typography,
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
DialogTitle,
|
||||||
|
DialogContent,
|
||||||
|
DialogActions,
|
||||||
|
Alert,
|
||||||
|
CircularProgress,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
ListItemText,
|
||||||
|
ListItemSecondaryAction,
|
||||||
|
IconButton,
|
||||||
|
Divider,
|
||||||
|
TextField,
|
||||||
|
Chip,
|
||||||
|
} from '@mui/material';
|
||||||
|
import {
|
||||||
|
Fingerprint,
|
||||||
|
Add,
|
||||||
|
Delete,
|
||||||
|
Edit,
|
||||||
|
CheckCircle,
|
||||||
|
Warning,
|
||||||
|
} from '@mui/icons-material';
|
||||||
|
import { biometricApi, type BiometricCredential } from '@/lib/api/biometric';
|
||||||
|
import { startRegistration } from '@simplewebauthn/browser';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { formatDistanceToNow } from 'date-fns';
|
||||||
|
|
||||||
|
export function BiometricSettings() {
|
||||||
|
const [credentials, setCredentials] = useState<BiometricCredential[]>([]);
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [successMessage, setSuccessMessage] = useState<string | null>(null);
|
||||||
|
const [isSupported, setIsSupported] = useState(false);
|
||||||
|
const [isPlatformAvailable, setIsPlatformAvailable] = useState(false);
|
||||||
|
|
||||||
|
// Add credential dialog
|
||||||
|
const [addDialogOpen, setAddDialogOpen] = useState(false);
|
||||||
|
const [isAdding, setIsAdding] = useState(false);
|
||||||
|
const [credentialName, setCredentialName] = useState('');
|
||||||
|
|
||||||
|
// Edit credential dialog
|
||||||
|
const [editDialogOpen, setEditDialogOpen] = useState(false);
|
||||||
|
const [credentialToEdit, setCredentialToEdit] = useState<BiometricCredential | null>(null);
|
||||||
|
const [editName, setEditName] = useState('');
|
||||||
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
|
|
||||||
|
// Delete credential dialog
|
||||||
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||||
|
const [credentialToDelete, setCredentialToDelete] = useState<BiometricCredential | null>(null);
|
||||||
|
const [isDeleting, setIsDeleting] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
checkSupport();
|
||||||
|
loadCredentials();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const checkSupport = async () => {
|
||||||
|
const supported = biometricApi.isSupported();
|
||||||
|
setIsSupported(supported);
|
||||||
|
|
||||||
|
if (supported) {
|
||||||
|
const available = await biometricApi.isPlatformAuthenticatorAvailable();
|
||||||
|
setIsPlatformAvailable(available);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadCredentials = async () => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const response = await biometricApi.getCredentials();
|
||||||
|
setCredentials(response.credentials);
|
||||||
|
setError(null);
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error('Failed to load biometric credentials:', err);
|
||||||
|
setError('Failed to load biometric credentials');
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddCredential = async () => {
|
||||||
|
try {
|
||||||
|
setIsAdding(true);
|
||||||
|
setError(null);
|
||||||
|
|
||||||
|
// Get registration options from server
|
||||||
|
const options = await biometricApi.getRegistrationOptions(credentialName || undefined);
|
||||||
|
|
||||||
|
// Start WebAuthn registration (triggers Face ID/Touch ID/Windows Hello)
|
||||||
|
const registrationResponse = await startRegistration(options);
|
||||||
|
|
||||||
|
// Send response to server for verification
|
||||||
|
await biometricApi.verifyRegistration(registrationResponse, credentialName || undefined);
|
||||||
|
|
||||||
|
setSuccessMessage('Biometric credential added successfully!');
|
||||||
|
setAddDialogOpen(false);
|
||||||
|
setCredentialName('');
|
||||||
|
await loadCredentials();
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error('Failed to add biometric credential:', err);
|
||||||
|
if (err.name === 'NotAllowedError') {
|
||||||
|
setError('Biometric authentication was cancelled');
|
||||||
|
} else if (err.name === 'NotSupportedError') {
|
||||||
|
setError('Biometric authentication is not supported on this device');
|
||||||
|
} else {
|
||||||
|
setError(err.response?.data?.message || err.message || 'Failed to add biometric credential');
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setIsAdding(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditCredential = async () => {
|
||||||
|
if (!credentialToEdit || !editName.trim()) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsEditing(true);
|
||||||
|
await biometricApi.updateCredentialName(credentialToEdit.id, editName.trim());
|
||||||
|
setSuccessMessage('Credential name updated successfully');
|
||||||
|
setEditDialogOpen(false);
|
||||||
|
setCredentialToEdit(null);
|
||||||
|
setEditName('');
|
||||||
|
await loadCredentials();
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error('Failed to update credential name:', err);
|
||||||
|
setError(err.response?.data?.message || 'Failed to update credential name');
|
||||||
|
} finally {
|
||||||
|
setIsEditing(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteCredential = async () => {
|
||||||
|
if (!credentialToDelete) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsDeleting(true);
|
||||||
|
await biometricApi.deleteCredential(credentialToDelete.id);
|
||||||
|
setSuccessMessage('Biometric credential removed successfully');
|
||||||
|
setDeleteDialogOpen(false);
|
||||||
|
setCredentialToDelete(null);
|
||||||
|
await loadCredentials();
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error('Failed to delete credential:', err);
|
||||||
|
setError(err.response?.data?.message || 'Failed to delete credential');
|
||||||
|
} finally {
|
||||||
|
setIsDeleting(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isLoading) {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardContent sx={{ display: 'flex', justifyContent: 'center', py: 4 }}>
|
||||||
|
<CircularProgress />
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isSupported) {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardContent>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 2 }}>
|
||||||
|
<Fingerprint color="disabled" />
|
||||||
|
<Typography variant="h6" fontWeight="600" color="text.secondary">
|
||||||
|
Biometric Authentication
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Alert severity="info">
|
||||||
|
Biometric authentication is not supported in your browser. Please use a modern browser like Chrome,
|
||||||
|
Safari, or Edge.
|
||||||
|
</Alert>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPlatformAvailable) {
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardContent>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 2 }}>
|
||||||
|
<Fingerprint color="disabled" />
|
||||||
|
<Typography variant="h6" fontWeight="600" color="text.secondary">
|
||||||
|
Biometric Authentication
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
<Alert severity="warning" icon={<Warning />}>
|
||||||
|
No biometric authenticator found on this device. To use Face ID, Touch ID, or Windows Hello, please
|
||||||
|
ensure your device has biometric hardware enabled.
|
||||||
|
</Alert>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card>
|
||||||
|
<CardContent>
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 2 }}>
|
||||||
|
<Fingerprint color="primary" />
|
||||||
|
<Typography variant="h6" fontWeight="600">
|
||||||
|
Biometric Authentication
|
||||||
|
</Typography>
|
||||||
|
<Chip
|
||||||
|
label={`${credentials.length} credential${credentials.length !== 1 ? 's' : ''}`}
|
||||||
|
size="small"
|
||||||
|
sx={{ ml: 'auto' }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
|
||||||
|
Use Face ID, Touch ID, Windows Hello, or other biometric methods to sign in securely without a
|
||||||
|
password.
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<Alert severity="error" sx={{ mb: 2 }} onClose={() => setError(null)}>
|
||||||
|
{error}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{successMessage && (
|
||||||
|
<Alert severity="success" sx={{ mb: 2 }} onClose={() => setSuccessMessage(null)}>
|
||||||
|
{successMessage}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{credentials.length === 0 ? (
|
||||||
|
<Alert severity="info" sx={{ mb: 2 }}>
|
||||||
|
No biometric credentials enrolled. Add one to enable biometric sign-in.
|
||||||
|
</Alert>
|
||||||
|
) : (
|
||||||
|
<List>
|
||||||
|
{credentials.map((credential, index) => (
|
||||||
|
<Box key={credential.id}>
|
||||||
|
{index > 0 && <Divider />}
|
||||||
|
<ListItem>
|
||||||
|
<ListItemText
|
||||||
|
primary={
|
||||||
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||||
|
<Typography variant="body1">
|
||||||
|
{credential.friendlyName || 'Unnamed Credential'}
|
||||||
|
</Typography>
|
||||||
|
{credential.backedUp && (
|
||||||
|
<Chip label="Synced" color="info" size="small" icon={<CheckCircle />} />
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
secondary={
|
||||||
|
<Box>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
Device Type: {credential.deviceType || 'Unknown'}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
Added: {formatDistanceToNow(new Date(credential.createdAt))} ago
|
||||||
|
</Typography>
|
||||||
|
{credential.lastUsed && (
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
Last used: {formatDistanceToNow(new Date(credential.lastUsed))} ago
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<ListItemSecondaryAction>
|
||||||
|
<Box sx={{ display: 'flex', gap: 1 }}>
|
||||||
|
<IconButton
|
||||||
|
edge="end"
|
||||||
|
onClick={() => {
|
||||||
|
setCredentialToEdit(credential);
|
||||||
|
setEditName(credential.friendlyName || '');
|
||||||
|
setEditDialogOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Edit />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton
|
||||||
|
edge="end"
|
||||||
|
onClick={() => {
|
||||||
|
setCredentialToDelete(credential);
|
||||||
|
setDeleteDialogOpen(true);
|
||||||
|
}}
|
||||||
|
color="error"
|
||||||
|
>
|
||||||
|
<Delete />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
</ListItemSecondaryAction>
|
||||||
|
</ListItem>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
startIcon={<Add />}
|
||||||
|
onClick={() => setAddDialogOpen(true)}
|
||||||
|
fullWidth
|
||||||
|
sx={{ mt: 2 }}
|
||||||
|
>
|
||||||
|
Add Biometric Credential
|
||||||
|
</Button>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Add Credential Dialog */}
|
||||||
|
<Dialog open={addDialogOpen} onClose={() => !isAdding && setAddDialogOpen(false)} maxWidth="sm" fullWidth>
|
||||||
|
<DialogTitle>Add Biometric Credential</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
|
||||||
|
You'll be prompted to use your device's biometric authentication (Face ID, Touch ID, Windows Hello,
|
||||||
|
etc.) to create a new credential.
|
||||||
|
</Typography>
|
||||||
|
<TextField
|
||||||
|
label="Credential Name (Optional)"
|
||||||
|
value={credentialName}
|
||||||
|
onChange={(e) => setCredentialName(e.target.value)}
|
||||||
|
fullWidth
|
||||||
|
disabled={isAdding}
|
||||||
|
placeholder="e.g., My Laptop, iPhone 15"
|
||||||
|
helperText="Give this credential a friendly name to identify it later"
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={() => setAddDialogOpen(false)} disabled={isAdding}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleAddCredential} variant="contained" disabled={isAdding}>
|
||||||
|
{isAdding ? <CircularProgress size={20} /> : 'Add Credential'}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
{/* Edit Credential Dialog */}
|
||||||
|
<Dialog
|
||||||
|
open={editDialogOpen}
|
||||||
|
onClose={() => !isEditing && setEditDialogOpen(false)}
|
||||||
|
maxWidth="sm"
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
<DialogTitle>Edit Credential Name</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<TextField
|
||||||
|
label="Credential Name"
|
||||||
|
value={editName}
|
||||||
|
onChange={(e) => setEditName(e.target.value)}
|
||||||
|
fullWidth
|
||||||
|
disabled={isEditing}
|
||||||
|
autoFocus
|
||||||
|
sx={{ mt: 1 }}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={() => setEditDialogOpen(false)} disabled={isEditing}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleEditCredential} variant="contained" disabled={isEditing || !editName.trim()}>
|
||||||
|
{isEditing ? <CircularProgress size={20} /> : 'Save'}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
{/* Delete Credential Dialog */}
|
||||||
|
<Dialog
|
||||||
|
open={deleteDialogOpen}
|
||||||
|
onClose={() => !isDeleting && setDeleteDialogOpen(false)}
|
||||||
|
maxWidth="sm"
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
<DialogTitle>Remove Biometric Credential?</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<Alert severity="warning" sx={{ mb: 2 }}>
|
||||||
|
This will remove the biometric credential from your account. You won't be able to use it to sign in.
|
||||||
|
</Alert>
|
||||||
|
{credentialToDelete && (
|
||||||
|
<Typography variant="body2">
|
||||||
|
<strong>Credential:</strong> {credentialToDelete.friendlyName || 'Unnamed Credential'}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={() => setDeleteDialogOpen(false)} disabled={isDeleting}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleDeleteCredential} variant="contained" color="error" disabled={isDeleting}>
|
||||||
|
{isDeleting ? <CircularProgress size={20} /> : 'Remove'}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
135
maternal-web/lib/api/biometric.ts
Normal file
135
maternal-web/lib/api/biometric.ts
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3020';
|
||||||
|
|
||||||
|
export interface BiometricCredential {
|
||||||
|
id: string;
|
||||||
|
friendlyName?: string;
|
||||||
|
deviceType?: string;
|
||||||
|
createdAt: Date;
|
||||||
|
lastUsed?: Date;
|
||||||
|
backedUp: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const biometricApi = {
|
||||||
|
// Check if user has biometric credentials
|
||||||
|
async hasCredentials(): Promise<{ success: boolean; hasCredentials: boolean }> {
|
||||||
|
const response = await axios.get(`${API_BASE_URL}/api/v1/auth/biometric/has-credentials`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get all biometric credentials for current user
|
||||||
|
async getCredentials(): Promise<{ success: boolean; credentials: BiometricCredential[] }> {
|
||||||
|
const response = await axios.get(`${API_BASE_URL}/api/v1/auth/biometric/credentials`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get registration options (start enrollment process)
|
||||||
|
async getRegistrationOptions(friendlyName?: string): Promise<any> {
|
||||||
|
const response = await axios.post(
|
||||||
|
`${API_BASE_URL}/api/v1/auth/biometric/register/options`,
|
||||||
|
{ friendlyName },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Verify registration response (complete enrollment)
|
||||||
|
async verifyRegistration(
|
||||||
|
response: any,
|
||||||
|
friendlyName?: string
|
||||||
|
): Promise<{ success: boolean; credentialId: string; message: string }> {
|
||||||
|
const verifyResponse = await axios.post(
|
||||||
|
`${API_BASE_URL}/api/v1/auth/biometric/register/verify`,
|
||||||
|
{ response, friendlyName },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return verifyResponse.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Get authentication options (start login process)
|
||||||
|
async getAuthenticationOptions(email?: string): Promise<any> {
|
||||||
|
const response = await axios.post(`${API_BASE_URL}/api/v1/auth/biometric/authenticate/options`, {
|
||||||
|
email,
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Verify authentication response (complete login)
|
||||||
|
async verifyAuthentication(
|
||||||
|
response: any,
|
||||||
|
email?: string,
|
||||||
|
deviceInfo?: { deviceId: string; platform: string }
|
||||||
|
): Promise<{ success: boolean; message: string; user: any; tokens: any }> {
|
||||||
|
const verifyResponse = await axios.post(
|
||||||
|
`${API_BASE_URL}/api/v1/auth/biometric/authenticate/verify`,
|
||||||
|
{ response, email, deviceInfo }
|
||||||
|
);
|
||||||
|
return verifyResponse.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Delete a credential
|
||||||
|
async deleteCredential(credentialId: string): Promise<{ success: boolean; message: string }> {
|
||||||
|
const response = await axios.delete(
|
||||||
|
`${API_BASE_URL}/api/v1/auth/biometric/credentials/${credentialId}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Update credential name
|
||||||
|
async updateCredentialName(
|
||||||
|
credentialId: string,
|
||||||
|
friendlyName: string
|
||||||
|
): Promise<{ success: boolean; message: string }> {
|
||||||
|
const response = await axios.patch(
|
||||||
|
`${API_BASE_URL}/api/v1/auth/biometric/credentials/${credentialId}`,
|
||||||
|
{ friendlyName },
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${localStorage.getItem('accessToken')}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Check if WebAuthn is supported in this browser
|
||||||
|
isSupported(): boolean {
|
||||||
|
return (
|
||||||
|
typeof window !== 'undefined' &&
|
||||||
|
window.PublicKeyCredential !== undefined &&
|
||||||
|
typeof window.PublicKeyCredential === 'function'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Check if platform authenticator (Face ID, Touch ID, Windows Hello) is available
|
||||||
|
async isPlatformAuthenticatorAvailable(): Promise<boolean> {
|
||||||
|
if (!this.isSupported()) return false;
|
||||||
|
try {
|
||||||
|
return await window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
579
maternal-web/package-lock.json
generated
579
maternal-web/package-lock.json
generated
@@ -15,6 +15,7 @@
|
|||||||
"@mui/material": "^5.18.0",
|
"@mui/material": "^5.18.0",
|
||||||
"@mui/material-nextjs": "^7.3.2",
|
"@mui/material-nextjs": "^7.3.2",
|
||||||
"@reduxjs/toolkit": "^2.9.0",
|
"@reduxjs/toolkit": "^2.9.0",
|
||||||
|
"@simplewebauthn/browser": "^13.2.0",
|
||||||
"@tanstack/react-query": "^5.90.2",
|
"@tanstack/react-query": "^5.90.2",
|
||||||
"axios": "^1.12.2",
|
"axios": "^1.12.2",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
@@ -3160,7 +3161,7 @@
|
|||||||
"version": "1.55.1",
|
"version": "1.55.1",
|
||||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.55.1.tgz",
|
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.55.1.tgz",
|
||||||
"integrity": "sha512-IVAh/nOJaw6W9g+RJVlIQJ6gSiER+ae6mKQ5CX1bERzQgbC1VSeBlwdvczT7pxb0GWiyrxH4TGKbMfDb4Sq/ig==",
|
"integrity": "sha512-IVAh/nOJaw6W9g+RJVlIQJ6gSiER+ae6mKQ5CX1bERzQgbC1VSeBlwdvczT7pxb0GWiyrxH4TGKbMfDb4Sq/ig==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.55.1"
|
"playwright": "1.55.1"
|
||||||
@@ -3353,6 +3354,12 @@
|
|||||||
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
|
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@simplewebauthn/browser": {
|
||||||
|
"version": "13.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@simplewebauthn/browser/-/browser-13.2.0.tgz",
|
||||||
|
"integrity": "sha512-N3fuA1AAnTo5gCStYoIoiasPccC+xPLx2YU88Dv0GeAmPQTWHETlZQq5xZ0DgUq1H9loXMWQH5qqUjcI7BHJ1A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@sinclair/typebox": {
|
"node_modules/@sinclair/typebox": {
|
||||||
"version": "0.34.41",
|
"version": "0.34.41",
|
||||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz",
|
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz",
|
||||||
@@ -3452,27 +3459,6 @@
|
|||||||
"react": "^18 || ^19"
|
"react": "^18 || ^19"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@testing-library/dom": {
|
|
||||||
"version": "10.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz",
|
|
||||||
"integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/code-frame": "^7.10.4",
|
|
||||||
"@babel/runtime": "^7.12.5",
|
|
||||||
"@types/aria-query": "^5.0.1",
|
|
||||||
"aria-query": "5.3.0",
|
|
||||||
"dom-accessibility-api": "^0.5.9",
|
|
||||||
"lz-string": "^1.5.0",
|
|
||||||
"picocolors": "1.1.1",
|
|
||||||
"pretty-format": "^27.0.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@testing-library/jest-dom": {
|
"node_modules/@testing-library/jest-dom": {
|
||||||
"version": "6.9.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.0.tgz",
|
||||||
@@ -3553,19 +3539,11 @@
|
|||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/aria-query": {
|
|
||||||
"version": "5.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
|
|
||||||
"integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/@types/babel__core": {
|
"node_modules/@types/babel__core": {
|
||||||
"version": "7.20.5",
|
"version": "7.20.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
||||||
"integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
|
"integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/parser": "^7.20.7",
|
"@babel/parser": "^7.20.7",
|
||||||
@@ -3579,7 +3557,7 @@
|
|||||||
"version": "7.27.0",
|
"version": "7.27.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
|
||||||
"integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
|
"integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.0.0"
|
"@babel/types": "^7.0.0"
|
||||||
@@ -3589,7 +3567,7 @@
|
|||||||
"version": "7.4.4",
|
"version": "7.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
|
||||||
"integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
|
"integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/parser": "^7.1.0",
|
"@babel/parser": "^7.1.0",
|
||||||
@@ -3600,7 +3578,7 @@
|
|||||||
"version": "7.28.0",
|
"version": "7.28.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
|
||||||
"integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
|
"integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.28.2"
|
"@babel/types": "^7.28.2"
|
||||||
@@ -3669,28 +3647,6 @@
|
|||||||
"integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
|
"integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/eslint": {
|
|
||||||
"version": "9.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
|
|
||||||
"integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@types/estree": "*",
|
|
||||||
"@types/json-schema": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/eslint-scope": {
|
|
||||||
"version": "3.7.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
|
|
||||||
"integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@types/eslint": "*",
|
|
||||||
"@types/estree": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||||
@@ -3829,6 +3785,7 @@
|
|||||||
"version": "18.3.25",
|
"version": "18.3.25",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.25.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.25.tgz",
|
||||||
"integrity": "sha512-oSVZmGtDPmRZtVDqvdKUi/qgCsWp5IDY29wp8na8Bj4B3cc99hfNzvNhlMkVVxctkAOGUA3Km7MMpBHAnWfcIA==",
|
"integrity": "sha512-oSVZmGtDPmRZtVDqvdKUi/qgCsWp5IDY29wp8na8Bj4B3cc99hfNzvNhlMkVVxctkAOGUA3Km7MMpBHAnWfcIA==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/prop-types": "*",
|
"@types/prop-types": "*",
|
||||||
@@ -4179,181 +4136,6 @@
|
|||||||
"win32"
|
"win32"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/ast": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@webassemblyjs/helper-numbers": "1.13.2",
|
|
||||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/floating-point-hex-parser": {
|
|
||||||
"version": "1.13.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
|
|
||||||
"integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/helper-api-error": {
|
|
||||||
"version": "1.13.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
|
|
||||||
"integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/helper-buffer": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/helper-numbers": {
|
|
||||||
"version": "1.13.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
|
|
||||||
"integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@webassemblyjs/floating-point-hex-parser": "1.13.2",
|
|
||||||
"@webassemblyjs/helper-api-error": "1.13.2",
|
|
||||||
"@xtuc/long": "4.2.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/helper-wasm-bytecode": {
|
|
||||||
"version": "1.13.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
|
|
||||||
"integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/helper-wasm-section": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@webassemblyjs/ast": "1.14.1",
|
|
||||||
"@webassemblyjs/helper-buffer": "1.14.1",
|
|
||||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
|
|
||||||
"@webassemblyjs/wasm-gen": "1.14.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/ieee754": {
|
|
||||||
"version": "1.13.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
|
|
||||||
"integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@xtuc/ieee754": "^1.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/leb128": {
|
|
||||||
"version": "1.13.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
|
|
||||||
"integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@xtuc/long": "4.2.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/utf8": {
|
|
||||||
"version": "1.13.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
|
|
||||||
"integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/wasm-edit": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@webassemblyjs/ast": "1.14.1",
|
|
||||||
"@webassemblyjs/helper-buffer": "1.14.1",
|
|
||||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
|
|
||||||
"@webassemblyjs/helper-wasm-section": "1.14.1",
|
|
||||||
"@webassemblyjs/wasm-gen": "1.14.1",
|
|
||||||
"@webassemblyjs/wasm-opt": "1.14.1",
|
|
||||||
"@webassemblyjs/wasm-parser": "1.14.1",
|
|
||||||
"@webassemblyjs/wast-printer": "1.14.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/wasm-gen": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@webassemblyjs/ast": "1.14.1",
|
|
||||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
|
|
||||||
"@webassemblyjs/ieee754": "1.13.2",
|
|
||||||
"@webassemblyjs/leb128": "1.13.2",
|
|
||||||
"@webassemblyjs/utf8": "1.13.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/wasm-opt": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@webassemblyjs/ast": "1.14.1",
|
|
||||||
"@webassemblyjs/helper-buffer": "1.14.1",
|
|
||||||
"@webassemblyjs/wasm-gen": "1.14.1",
|
|
||||||
"@webassemblyjs/wasm-parser": "1.14.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/wasm-parser": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@webassemblyjs/ast": "1.14.1",
|
|
||||||
"@webassemblyjs/helper-api-error": "1.13.2",
|
|
||||||
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
|
|
||||||
"@webassemblyjs/ieee754": "1.13.2",
|
|
||||||
"@webassemblyjs/leb128": "1.13.2",
|
|
||||||
"@webassemblyjs/utf8": "1.13.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@webassemblyjs/wast-printer": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@webassemblyjs/ast": "1.14.1",
|
|
||||||
"@xtuc/long": "4.2.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@xtuc/ieee754": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
|
|
||||||
"license": "BSD-3-Clause",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/@xtuc/long": {
|
|
||||||
"version": "4.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
|
|
||||||
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.15.0",
|
"version": "8.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||||
@@ -4366,19 +4148,6 @@
|
|||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/acorn-import-phases": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
|
|
||||||
"integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.13.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"acorn": "^8.14.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/agent-base": {
|
"node_modules/agent-base": {
|
||||||
"version": "7.1.4",
|
"version": "7.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
||||||
@@ -5182,16 +4951,6 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/chrome-trace-event": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
|
|
||||||
"integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ci-info": {
|
"node_modules/ci-info": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz",
|
||||||
@@ -6021,14 +5780,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/dom-accessibility-api": {
|
|
||||||
"version": "0.5.16",
|
|
||||||
"resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
|
|
||||||
"integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/dom-helpers": {
|
"node_modules/dom-helpers": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
||||||
@@ -6149,20 +5900,6 @@
|
|||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/enhanced-resolve": {
|
|
||||||
"version": "5.18.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
|
|
||||||
"integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"graceful-fs": "^4.2.4",
|
|
||||||
"tapable": "^2.2.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.13.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/entities": {
|
"node_modules/entities": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
|
||||||
@@ -6271,13 +6008,6 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/es-module-lexer": {
|
|
||||||
"version": "1.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
|
|
||||||
"integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/es-object-atoms": {
|
"node_modules/es-object-atoms": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||||
@@ -6353,20 +6083,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-scope": {
|
|
||||||
"version": "5.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
|
|
||||||
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"esrecurse": "^4.3.0",
|
|
||||||
"estraverse": "^4.1.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/esprima": {
|
"node_modules/esprima": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||||
@@ -6381,39 +6097,6 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"estraverse": "^5.2.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/esrecurse/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",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/estraverse": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/estree-walker": {
|
"node_modules/estree-walker": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
|
||||||
@@ -6435,16 +6118,6 @@
|
|||||||
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
|
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/events": {
|
|
||||||
"version": "3.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
|
||||||
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.8.x"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/execa": {
|
"node_modules/execa": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
|
||||||
@@ -6952,13 +6625,6 @@
|
|||||||
"node": ">=10.13.0"
|
"node": ">=10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/glob-to-regexp": {
|
|
||||||
"version": "0.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
|
|
||||||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/globalthis": {
|
"node_modules/globalthis": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
|
||||||
@@ -9385,16 +9051,6 @@
|
|||||||
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/loader-runner": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.11.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/loader-utils": {
|
"node_modules/loader-utils": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
|
||||||
@@ -9472,17 +9128,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/lz-string": {
|
|
||||||
"version": "1.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
|
|
||||||
"integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
|
||||||
"lz-string": "bin/bin.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.9",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
|
||||||
@@ -9716,6 +9361,7 @@
|
|||||||
"version": "2.6.2",
|
"version": "2.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/next": {
|
"node_modules/next": {
|
||||||
@@ -10549,7 +10195,7 @@
|
|||||||
"version": "1.55.1",
|
"version": "1.55.1",
|
||||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.1.tgz",
|
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.1.tgz",
|
||||||
"integrity": "sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==",
|
"integrity": "sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.55.1"
|
"playwright-core": "1.55.1"
|
||||||
@@ -10568,7 +10214,7 @@
|
|||||||
"version": "1.55.1",
|
"version": "1.55.1",
|
||||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.1.tgz",
|
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.1.tgz",
|
||||||
"integrity": "sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==",
|
"integrity": "sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright-core": "cli.js"
|
"playwright-core": "cli.js"
|
||||||
@@ -10733,55 +10379,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pretty-format": {
|
|
||||||
"version": "27.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
|
|
||||||
"integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-regex": "^5.0.1",
|
|
||||||
"ansi-styles": "^5.0.0",
|
|
||||||
"react-is": "^17.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pretty-format/node_modules/ansi-regex": {
|
|
||||||
"version": "5.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
|
||||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pretty-format/node_modules/ansi-styles": {
|
|
||||||
"version": "5.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
|
||||||
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pretty-format/node_modules/react-is": {
|
|
||||||
"version": "17.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
|
||||||
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/prop-types": {
|
"node_modules/prop-types": {
|
||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
@@ -12304,20 +11901,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tapable": {
|
|
||||||
"version": "2.2.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz",
|
|
||||||
"integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/webpack"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/temp-dir": {
|
"node_modules/temp-dir": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz",
|
||||||
@@ -13075,20 +12658,6 @@
|
|||||||
"makeerror": "1.0.12"
|
"makeerror": "1.0.12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/watchpack": {
|
|
||||||
"version": "2.4.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz",
|
|
||||||
"integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"glob-to-regexp": "^0.4.1",
|
|
||||||
"graceful-fs": "^4.1.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.13.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/web-vitals": {
|
"node_modules/web-vitals": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-5.1.0.tgz",
|
||||||
@@ -13101,122 +12670,6 @@
|
|||||||
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
|
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
|
||||||
"license": "BSD-2-Clause"
|
"license": "BSD-2-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/webpack": {
|
|
||||||
"version": "5.102.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.102.0.tgz",
|
|
||||||
"integrity": "sha512-hUtqAR3ZLVEYDEABdBioQCIqSoguHbFn1K7WlPPWSuXmx0031BD73PSE35jKyftdSh4YLDoQNgK4pqBt5Q82MA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@types/eslint-scope": "^3.7.7",
|
|
||||||
"@types/estree": "^1.0.8",
|
|
||||||
"@types/json-schema": "^7.0.15",
|
|
||||||
"@webassemblyjs/ast": "^1.14.1",
|
|
||||||
"@webassemblyjs/wasm-edit": "^1.14.1",
|
|
||||||
"@webassemblyjs/wasm-parser": "^1.14.1",
|
|
||||||
"acorn": "^8.15.0",
|
|
||||||
"acorn-import-phases": "^1.0.3",
|
|
||||||
"browserslist": "^4.24.5",
|
|
||||||
"chrome-trace-event": "^1.0.2",
|
|
||||||
"enhanced-resolve": "^5.17.3",
|
|
||||||
"es-module-lexer": "^1.2.1",
|
|
||||||
"eslint-scope": "5.1.1",
|
|
||||||
"events": "^3.2.0",
|
|
||||||
"glob-to-regexp": "^0.4.1",
|
|
||||||
"graceful-fs": "^4.2.11",
|
|
||||||
"json-parse-even-better-errors": "^2.3.1",
|
|
||||||
"loader-runner": "^4.2.0",
|
|
||||||
"mime-types": "^2.1.27",
|
|
||||||
"neo-async": "^2.6.2",
|
|
||||||
"schema-utils": "^4.3.2",
|
|
||||||
"tapable": "^2.2.3",
|
|
||||||
"terser-webpack-plugin": "^5.3.11",
|
|
||||||
"watchpack": "^2.4.4",
|
|
||||||
"webpack-sources": "^3.3.3"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"webpack": "bin/webpack.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.13.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/webpack"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"webpack-cli": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/webpack-sources": {
|
|
||||||
"version": "3.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz",
|
|
||||||
"integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.13.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/webpack/node_modules/ajv": {
|
|
||||||
"version": "8.17.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
|
||||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"fast-deep-equal": "^3.1.3",
|
|
||||||
"fast-uri": "^3.0.1",
|
|
||||||
"json-schema-traverse": "^1.0.0",
|
|
||||||
"require-from-string": "^2.0.2"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/epoberezkin"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/webpack/node_modules/ajv-keywords": {
|
|
||||||
"version": "5.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
|
||||||
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"fast-deep-equal": "^3.1.3"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"ajv": "^8.8.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/webpack/node_modules/json-schema-traverse": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/webpack/node_modules/schema-utils": {
|
|
||||||
"version": "4.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz",
|
|
||||||
"integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@types/json-schema": "^7.0.9",
|
|
||||||
"ajv": "^8.9.0",
|
|
||||||
"ajv-formats": "^2.1.1",
|
|
||||||
"ajv-keywords": "^5.1.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.13.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/webpack"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/whatwg-encoding": {
|
"node_modules/whatwg-encoding": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"@mui/material": "^5.18.0",
|
"@mui/material": "^5.18.0",
|
||||||
"@mui/material-nextjs": "^7.3.2",
|
"@mui/material-nextjs": "^7.3.2",
|
||||||
"@reduxjs/toolkit": "^2.9.0",
|
"@reduxjs/toolkit": "^2.9.0",
|
||||||
|
"@simplewebauthn/browser": "^13.2.0",
|
||||||
"@tanstack/react-query": "^5.90.2",
|
"@tanstack/react-query": "^5.90.2",
|
||||||
"axios": "^1.12.2",
|
"axios": "^1.12.2",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user