Enable RLS on rate limits table

This commit is contained in:
gpt-engineer-app[bot]
2025-10-14 19:24:54 +00:00
parent fd17234b67
commit 0a325d7c37
11 changed files with 821 additions and 252 deletions

View File

@@ -0,0 +1,89 @@
export type DeletionStep = 'warning' | 'confirm' | 'code';
export type DeletionDialogState = {
step: DeletionStep;
confirmationCode: string;
codeReceived: boolean;
scheduledDate: string;
isLoading: boolean;
error: string | null;
};
export type DeletionDialogAction =
| { type: 'CONTINUE_TO_CONFIRM' }
| { type: 'GO_BACK_TO_WARNING' }
| { type: 'REQUEST_DELETION'; payload: { scheduledDate: string } }
| { type: 'UPDATE_CODE'; payload: { code: string } }
| { type: 'TOGGLE_CODE_RECEIVED' }
| { type: 'SET_LOADING'; payload: boolean }
| { type: 'SET_ERROR'; payload: string | null }
| { type: 'RESET' };
export const initialState: DeletionDialogState = {
step: 'warning',
confirmationCode: '',
codeReceived: false,
scheduledDate: '',
isLoading: false,
error: null
};
export function deletionDialogReducer(
state: DeletionDialogState,
action: DeletionDialogAction
): DeletionDialogState {
switch (action.type) {
case 'CONTINUE_TO_CONFIRM':
return { ...state, step: 'confirm' };
case 'GO_BACK_TO_WARNING':
return { ...state, step: 'warning', error: null };
case 'REQUEST_DELETION':
return {
...state,
step: 'code',
scheduledDate: action.payload.scheduledDate,
isLoading: false,
error: null
};
case 'UPDATE_CODE':
// Only allow digits, max 6
const sanitized = action.payload.code.replace(/\D/g, '').slice(0, 6);
return { ...state, confirmationCode: sanitized };
case 'TOGGLE_CODE_RECEIVED':
return { ...state, codeReceived: !state.codeReceived };
case 'SET_LOADING':
return { ...state, isLoading: action.payload };
case 'SET_ERROR':
return { ...state, error: action.payload, isLoading: false };
case 'RESET':
return initialState;
default:
return state;
}
}
// Validation helpers
export const canProceedToConfirm = (state: DeletionDialogState): boolean => {
return state.step === 'warning' && !state.isLoading;
};
export const canRequestDeletion = (state: DeletionDialogState): boolean => {
return state.step === 'confirm' && !state.isLoading;
};
export const canConfirmDeletion = (state: DeletionDialogState): boolean => {
return (
state.step === 'code' &&
state.confirmationCode.length === 6 &&
state.codeReceived &&
!state.isLoading
);
};

63
src/lib/errorHandler.ts Normal file
View File

@@ -0,0 +1,63 @@
import { toast } from 'sonner';
import { logger } from './logger';
export type ErrorContext = {
action: string;
userId?: string;
metadata?: Record<string, any>;
};
export class AppError extends Error {
constructor(
message: string,
public code: string,
public userMessage?: string
) {
super(message);
this.name = 'AppError';
}
}
export const handleError = (
error: unknown,
context: ErrorContext
): void => {
const errorMessage = error instanceof AppError
? error.userMessage || error.message
: error instanceof Error
? error.message
: 'An unexpected error occurred';
// Log to console/monitoring
logger.error('Error occurred', {
...context,
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined
});
// Show user-friendly toast
toast.error(context.action, {
description: errorMessage,
duration: 5000
});
};
export const handleSuccess = (
title: string,
description?: string
): void => {
toast.success(title, {
description,
duration: 3000
});
};
export const handleInfo = (
title: string,
description?: string
): void => {
toast.info(title, {
description,
duration: 4000
});
};

View File

@@ -7,14 +7,24 @@
const isDev = import.meta.env.DEV;
type LogContext = {
[key: string]: any;
};
export const logger = {
log: (...args: any[]) => {
if (isDev) console.log(...args);
},
error: (...args: any[]) => {
console.error(...args); // Always log errors
error: (message: string, context?: LogContext) => {
console.error(message, context); // Always log errors
},
warn: (...args: any[]) => {
if (isDev) console.warn(...args);
},
info: (...args: any[]) => {
if (isDev) console.info(...args);
},
debug: (...args: any[]) => {
if (isDev) console.debug(...args);
}
};