@exyconn/common 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +259 -0
- package/dist/client/http/index.d.mts +85 -0
- package/dist/client/http/index.d.ts +85 -0
- package/dist/client/http/index.js +127 -0
- package/dist/client/http/index.js.map +1 -0
- package/dist/client/http/index.mjs +109 -0
- package/dist/client/http/index.mjs.map +1 -0
- package/dist/client/index.d.mts +7 -0
- package/dist/client/index.d.ts +7 -0
- package/dist/client/index.js +964 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/index.mjs +889 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/client/logger/index.d.mts +53 -0
- package/dist/client/logger/index.d.ts +53 -0
- package/dist/client/logger/index.js +120 -0
- package/dist/client/logger/index.js.map +1 -0
- package/dist/client/logger/index.mjs +116 -0
- package/dist/client/logger/index.mjs.map +1 -0
- package/dist/client/utils/index.d.mts +285 -0
- package/dist/client/utils/index.d.ts +285 -0
- package/dist/client/utils/index.js +403 -0
- package/dist/client/utils/index.js.map +1 -0
- package/dist/client/utils/index.mjs +362 -0
- package/dist/client/utils/index.mjs.map +1 -0
- package/dist/index-BNdT-2X4.d.ts +229 -0
- package/dist/index-CcrANHAQ.d.mts +59 -0
- package/dist/index-ClWtDfwk.d.ts +833 -0
- package/dist/index-DSW6JfD-.d.mts +833 -0
- package/dist/index-Du0LLt9f.d.mts +229 -0
- package/dist/index-iTKxFa78.d.ts +59 -0
- package/dist/index.d.mts +171 -0
- package/dist/index.d.ts +171 -0
- package/dist/index.js +3806 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3792 -0
- package/dist/index.mjs.map +1 -0
- package/dist/response.types-D--UhLJq.d.mts +67 -0
- package/dist/response.types-D--UhLJq.d.ts +67 -0
- package/dist/server/db/index.d.mts +38 -0
- package/dist/server/db/index.d.ts +38 -0
- package/dist/server/db/index.js +68 -0
- package/dist/server/db/index.js.map +1 -0
- package/dist/server/db/index.mjs +60 -0
- package/dist/server/db/index.mjs.map +1 -0
- package/dist/server/enums/index.d.mts +46 -0
- package/dist/server/enums/index.d.ts +46 -0
- package/dist/server/enums/index.js +48 -0
- package/dist/server/enums/index.js.map +1 -0
- package/dist/server/enums/index.mjs +43 -0
- package/dist/server/enums/index.mjs.map +1 -0
- package/dist/server/index.d.mts +9 -0
- package/dist/server/index.d.ts +9 -0
- package/dist/server/index.js +569 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/index.mjs +523 -0
- package/dist/server/index.mjs.map +1 -0
- package/dist/server/logger/index.d.mts +34 -0
- package/dist/server/logger/index.d.ts +34 -0
- package/dist/server/logger/index.js +125 -0
- package/dist/server/logger/index.js.map +1 -0
- package/dist/server/logger/index.mjs +113 -0
- package/dist/server/logger/index.mjs.map +1 -0
- package/dist/server/middleware/index.d.mts +56 -0
- package/dist/server/middleware/index.d.ts +56 -0
- package/dist/server/middleware/index.js +128 -0
- package/dist/server/middleware/index.js.map +1 -0
- package/dist/server/middleware/index.mjs +118 -0
- package/dist/server/middleware/index.mjs.map +1 -0
- package/dist/server/response/index.d.mts +86 -0
- package/dist/server/response/index.d.ts +86 -0
- package/dist/server/response/index.js +140 -0
- package/dist/server/response/index.js.map +1 -0
- package/dist/server/response/index.mjs +126 -0
- package/dist/server/response/index.mjs.map +1 -0
- package/dist/server/utils/index.d.mts +69 -0
- package/dist/server/utils/index.d.ts +69 -0
- package/dist/server/utils/index.js +114 -0
- package/dist/server/utils/index.js.map +1 -0
- package/dist/server/utils/index.mjs +106 -0
- package/dist/server/utils/index.mjs.map +1 -0
- package/dist/shared/index.d.mts +4 -0
- package/dist/shared/index.d.ts +4 -0
- package/dist/shared/index.js +933 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/index.mjs +612 -0
- package/dist/shared/index.mjs.map +1 -0
- package/package.json +202 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/client/http/axios-instance.ts","../../src/client/http/response-parser.ts","../../src/client/logger/client-logger.ts","../../src/client/utils/date.ts","../../src/client/utils/clipboard.ts","../../src/client/utils/slug.ts","../../src/client/utils/events.ts","../../src/client/utils/api-urls.ts","../../src/client/utils/response-parser.ts","../../src/client/hooks/useLocalStorage.ts","../../src/client/hooks/useDebounce.ts","../../src/client/hooks/useCopyToClipboard.ts","../../src/client/hooks/usePageTitle.ts","../../src/client/hooks/useInterval.ts","../../src/client/hooks/useThemeDetector.ts","../../src/client/hooks/useSnackbar.ts","../../src/client/hooks/useMediaQuery.ts","../../src/client/hooks/useOnClickOutside.ts","../../src/client/hooks/useWindowSize.ts"],"names":["useState","useEffect","useCallback","query"],"mappings":"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","file":"index.mjs","sourcesContent":["import axios, { AxiosInstance, AxiosRequestConfig, AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios';\r\n\r\n/**\r\n * HTTP Client Configuration Options\r\n */\r\nexport interface HttpClientOptions {\r\n baseURL: string;\r\n timeout?: number;\r\n withCredentials?: boolean;\r\n getAuthToken?: () => string | null;\r\n onUnauthorized?: () => void;\r\n onServerError?: (error: AxiosError) => void;\r\n}\r\n\r\n/**\r\n * Create configured Axios instance\r\n */\r\nexport const createHttpClient = (options: HttpClientOptions): AxiosInstance => {\r\n const {\r\n baseURL,\r\n timeout = 30000,\r\n withCredentials = true,\r\n getAuthToken,\r\n onUnauthorized,\r\n onServerError,\r\n } = options;\r\n\r\n const instance = axios.create({\r\n baseURL,\r\n timeout,\r\n withCredentials,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n\r\n // Request interceptor - add auth token\r\n instance.interceptors.request.use(\r\n (config: InternalAxiosRequestConfig) => {\r\n if (getAuthToken) {\r\n const token = getAuthToken();\r\n if (token && config.headers) {\r\n config.headers.Authorization = `Bearer ${token}`;\r\n }\r\n }\r\n return config;\r\n },\r\n (error: unknown) => Promise.reject(error)\r\n );\r\n\r\n // Response interceptor - handle errors\r\n instance.interceptors.response.use(\r\n (response: AxiosResponse) => response,\r\n (error: AxiosError) => {\r\n if (error.response) {\r\n const status = error.response.status;\r\n\r\n // Handle 401 Unauthorized\r\n if (status === 401 && onUnauthorized) {\r\n onUnauthorized();\r\n }\r\n\r\n // Handle 5xx Server Errors\r\n if (status >= 500 && onServerError) {\r\n onServerError(error);\r\n }\r\n }\r\n\r\n return Promise.reject(error);\r\n }\r\n );\r\n\r\n return instance;\r\n};\r\n\r\n/**\r\n * Default request config helpers\r\n */\r\nexport const withFormData = (): AxiosRequestConfig => ({\r\n headers: {\r\n 'Content-Type': 'multipart/form-data',\r\n },\r\n});\r\n\r\nexport const withTimeout = (ms: number): AxiosRequestConfig => ({\r\n timeout: ms,\r\n});\r\n\r\nexport const withAbortSignal = (signal: AbortSignal): AxiosRequestConfig => ({\r\n signal,\r\n});\r\n\r\nexport default {\r\n createHttpClient,\r\n withFormData,\r\n withTimeout,\r\n withAbortSignal,\r\n};\r\n","import { AxiosResponse, AxiosError } from 'axios';\r\n\r\n/**\r\n * Standard API Response Structure\r\n */\r\nexport interface ApiResponse<T = unknown> {\r\n success: boolean;\r\n message: string;\r\n data?: T;\r\n error?: string;\r\n statusCode?: number;\r\n}\r\n\r\n/**\r\n * Paginated Response Structure\r\n */\r\nexport interface PaginatedResponse<T = unknown> extends ApiResponse<T[]> {\r\n pagination: {\r\n total: number;\r\n page: number;\r\n limit: number;\r\n totalPages: number;\r\n hasNextPage: boolean;\r\n hasPrevPage: boolean;\r\n };\r\n}\r\n\r\n/**\r\n * Parse successful API response\r\n */\r\nexport const parseResponse = <T>(response: AxiosResponse<ApiResponse<T>>): T | null => {\r\n if (response.data?.success && response.data?.data !== undefined) {\r\n return response.data.data;\r\n }\r\n return null;\r\n};\r\n\r\n/**\r\n * Parse API response with full metadata\r\n */\r\nexport const parseFullResponse = <T>(response: AxiosResponse<ApiResponse<T>>): ApiResponse<T> => {\r\n return response.data;\r\n};\r\n\r\n/**\r\n * Parse error from API response\r\n */\r\nexport const parseError = (error: AxiosError<ApiResponse>): string => {\r\n // Check for API error message\r\n if (error.response?.data?.message) {\r\n return error.response.data.message;\r\n }\r\n\r\n if (error.response?.data?.error) {\r\n return error.response.data.error;\r\n }\r\n\r\n // Check for network error\r\n if (error.code === 'ERR_NETWORK') {\r\n return 'Network error. Please check your connection.';\r\n }\r\n\r\n // Check for timeout\r\n if (error.code === 'ECONNABORTED') {\r\n return 'Request timed out. Please try again.';\r\n }\r\n\r\n // Default error message\r\n return error.message || 'An unexpected error occurred.';\r\n};\r\n\r\n/**\r\n * Check if response is successful\r\n */\r\nexport const isSuccess = <T>(response: AxiosResponse<ApiResponse<T>>): boolean => {\r\n return response.data?.success === true;\r\n};\r\n\r\n/**\r\n * Check if error is a specific status code\r\n */\r\nexport const isStatusError = (error: AxiosError, statusCode: number): boolean => {\r\n return error.response?.status === statusCode;\r\n};\r\n\r\n/**\r\n * Check if error is unauthorized (401)\r\n */\r\nexport const isUnauthorized = (error: AxiosError): boolean => {\r\n return isStatusError(error, 401);\r\n};\r\n\r\n/**\r\n * Check if error is forbidden (403)\r\n */\r\nexport const isForbidden = (error: AxiosError): boolean => {\r\n return isStatusError(error, 403);\r\n};\r\n\r\n/**\r\n * Check if error is not found (404)\r\n */\r\nexport const isNotFound = (error: AxiosError): boolean => {\r\n return isStatusError(error, 404);\r\n};\r\n\r\n/**\r\n * Check if error is server error (5xx)\r\n */\r\nexport const isServerError = (error: AxiosError): boolean => {\r\n const status = error.response?.status;\r\n return status !== undefined && status >= 500;\r\n};\r\n\r\nexport default {\r\n parseResponse,\r\n parseFullResponse,\r\n parseError,\r\n isSuccess,\r\n isStatusError,\r\n isUnauthorized,\r\n isForbidden,\r\n isNotFound,\r\n isServerError,\r\n};\r\n","/**\r\n * Log Levels\r\n */\r\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\r\n\r\n/**\r\n * Client Logger Configuration\r\n */\r\nexport interface ClientLoggerConfig {\r\n enabled?: boolean;\r\n minLevel?: LogLevel;\r\n prefix?: string;\r\n includeTimestamp?: boolean;\r\n remoteLogging?: {\r\n enabled: boolean;\r\n endpoint: string;\r\n batchSize?: number;\r\n flushInterval?: number;\r\n };\r\n}\r\n\r\n/**\r\n * Log Entry\r\n */\r\ninterface LogEntry {\r\n level: LogLevel;\r\n message: string;\r\n data?: unknown;\r\n timestamp: string;\r\n prefix?: string;\r\n}\r\n\r\nconst LOG_LEVELS: Record<LogLevel, number> = {\r\n debug: 0,\r\n info: 1,\r\n warn: 2,\r\n error: 3,\r\n};\r\n\r\n/**\r\n * Client-side logger with optional remote logging\r\n */\r\nexport class ClientLogger {\r\n private config: Required<Omit<ClientLoggerConfig, 'remoteLogging'>> & {\r\n remoteLogging?: ClientLoggerConfig['remoteLogging'];\r\n };\r\n private buffer: LogEntry[] = [];\r\n private flushTimer?: ReturnType<typeof setInterval>;\r\n\r\n constructor(config: ClientLoggerConfig = {}) {\r\n this.config = {\r\n enabled: config.enabled ?? (process.env.NODE_ENV !== 'production'),\r\n minLevel: config.minLevel ?? 'debug',\r\n prefix: config.prefix ?? '[App]',\r\n includeTimestamp: config.includeTimestamp ?? true,\r\n remoteLogging: config.remoteLogging,\r\n };\r\n\r\n // Setup remote logging flush interval\r\n if (this.config.remoteLogging?.enabled) {\r\n const interval = this.config.remoteLogging.flushInterval ?? 30000;\r\n this.flushTimer = setInterval(() => this.flush(), interval);\r\n }\r\n }\r\n\r\n private shouldLog(level: LogLevel): boolean {\r\n if (!this.config.enabled) return false;\r\n return LOG_LEVELS[level] >= LOG_LEVELS[this.config.minLevel];\r\n }\r\n\r\n private formatMessage(level: LogLevel, message: string): string {\r\n const parts: string[] = [];\r\n \r\n if (this.config.includeTimestamp) {\r\n parts.push(`[${new Date().toISOString()}]`);\r\n }\r\n \r\n parts.push(this.config.prefix);\r\n parts.push(`[${level.toUpperCase()}]`);\r\n parts.push(message);\r\n \r\n return parts.join(' ');\r\n }\r\n\r\n private log(level: LogLevel, message: string, data?: unknown): void {\r\n if (!this.shouldLog(level)) return;\r\n\r\n const formattedMessage = this.formatMessage(level, message);\r\n const entry: LogEntry = {\r\n level,\r\n message,\r\n data,\r\n timestamp: new Date().toISOString(),\r\n prefix: this.config.prefix,\r\n };\r\n\r\n // Console output\r\n switch (level) {\r\n case 'debug':\r\n console.debug(formattedMessage, data ?? '');\r\n break;\r\n case 'info':\r\n console.info(formattedMessage, data ?? '');\r\n break;\r\n case 'warn':\r\n console.warn(formattedMessage, data ?? '');\r\n break;\r\n case 'error':\r\n console.error(formattedMessage, data ?? '');\r\n break;\r\n }\r\n\r\n // Buffer for remote logging\r\n if (this.config.remoteLogging?.enabled) {\r\n this.buffer.push(entry);\r\n const batchSize = this.config.remoteLogging.batchSize ?? 10;\r\n if (this.buffer.length >= batchSize) {\r\n this.flush();\r\n }\r\n }\r\n }\r\n\r\n debug(message: string, data?: unknown): void {\r\n this.log('debug', message, data);\r\n }\r\n\r\n info(message: string, data?: unknown): void {\r\n this.log('info', message, data);\r\n }\r\n\r\n warn(message: string, data?: unknown): void {\r\n this.log('warn', message, data);\r\n }\r\n\r\n error(message: string, data?: unknown): void {\r\n this.log('error', message, data);\r\n }\r\n\r\n /**\r\n * Flush buffered logs to remote endpoint\r\n */\r\n async flush(): Promise<void> {\r\n if (!this.config.remoteLogging?.enabled || this.buffer.length === 0) return;\r\n\r\n const logs = [...this.buffer];\r\n this.buffer = [];\r\n\r\n try {\r\n await fetch(this.config.remoteLogging.endpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ logs }),\r\n });\r\n } catch (error) {\r\n // Re-add logs to buffer on failure (but limit size)\r\n this.buffer = [...logs, ...this.buffer].slice(0, 100);\r\n console.error('Failed to send logs to remote endpoint', error);\r\n }\r\n }\r\n\r\n /**\r\n * Cleanup logger (clear intervals)\r\n */\r\n destroy(): void {\r\n if (this.flushTimer) {\r\n clearInterval(this.flushTimer);\r\n }\r\n this.flush();\r\n }\r\n}\r\n\r\n/**\r\n * Create a new logger instance\r\n */\r\nexport const createClientLogger = (config?: ClientLoggerConfig): ClientLogger => {\r\n return new ClientLogger(config);\r\n};\r\n\r\n/**\r\n * Default logger instance\r\n */\r\nexport const clientLogger = new ClientLogger();\r\n\r\nexport default clientLogger;\r\n","/**\r\n * Format date to readable string\r\n * @param date - Date to format\r\n * @param locale - Locale for formatting (default: 'en-US')\r\n */\r\nexport const formatDate = (\r\n date: Date | string | number,\r\n locale: string = 'en-US'\r\n): string => {\r\n const dateObj = new Date(date);\r\n return dateObj.toLocaleDateString(locale, {\r\n year: 'numeric',\r\n month: 'long',\r\n day: 'numeric',\r\n });\r\n};\r\n\r\n/**\r\n * Format date with time\r\n */\r\nexport const formatDateTime = (\r\n date: Date | string | number,\r\n locale: string = 'en-US'\r\n): string => {\r\n const dateObj = new Date(date);\r\n return dateObj.toLocaleDateString(locale, {\r\n year: 'numeric',\r\n month: 'short',\r\n day: 'numeric',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n });\r\n};\r\n\r\n/**\r\n * Format date as relative time (e.g., \"2 hours ago\")\r\n */\r\nexport const formatRelativeTime = (date: Date | string | number): string => {\r\n const dateObj = new Date(date);\r\n const now = new Date();\r\n const diffInSeconds = Math.floor((now.getTime() - dateObj.getTime()) / 1000);\r\n\r\n const intervals: { label: string; seconds: number }[] = [\r\n { label: 'year', seconds: 31536000 },\r\n { label: 'month', seconds: 2592000 },\r\n { label: 'week', seconds: 604800 },\r\n { label: 'day', seconds: 86400 },\r\n { label: 'hour', seconds: 3600 },\r\n { label: 'minute', seconds: 60 },\r\n { label: 'second', seconds: 1 },\r\n ];\r\n\r\n for (const interval of intervals) {\r\n const count = Math.floor(diffInSeconds / interval.seconds);\r\n if (count >= 1) {\r\n return `${count} ${interval.label}${count !== 1 ? 's' : ''} ago`;\r\n }\r\n }\r\n\r\n return 'just now';\r\n};\r\n\r\n/**\r\n * Format date for input[type=\"date\"]\r\n */\r\nexport const formatDateForInput = (date: Date | string | number): string => {\r\n const dateObj = new Date(date);\r\n return dateObj.toISOString().split('T')[0];\r\n};\r\n\r\n/**\r\n * Format date for input[type=\"datetime-local\"]\r\n */\r\nexport const formatDateTimeForInput = (date: Date | string | number): string => {\r\n const dateObj = new Date(date);\r\n return dateObj.toISOString().slice(0, 16);\r\n};\r\n\r\n/**\r\n * Check if date is today\r\n */\r\nexport const isToday = (date: Date | string | number): boolean => {\r\n const dateObj = new Date(date);\r\n const today = new Date();\r\n return (\r\n dateObj.getDate() === today.getDate() &&\r\n dateObj.getMonth() === today.getMonth() &&\r\n dateObj.getFullYear() === today.getFullYear()\r\n );\r\n};\r\n\r\n/**\r\n * Check if date is in the past\r\n */\r\nexport const isPast = (date: Date | string | number): boolean => {\r\n return new Date(date).getTime() < Date.now();\r\n};\r\n\r\n/**\r\n * Check if date is in the future\r\n */\r\nexport const isFuture = (date: Date | string | number): boolean => {\r\n return new Date(date).getTime() > Date.now();\r\n};\r\n\r\n/**\r\n * Add days to a date\r\n */\r\nexport const addDays = (date: Date | string | number, days: number): Date => {\r\n const dateObj = new Date(date);\r\n dateObj.setDate(dateObj.getDate() + days);\r\n return dateObj;\r\n};\r\n\r\n/**\r\n * Get start of day\r\n */\r\nexport const startOfDay = (date: Date | string | number): Date => {\r\n const dateObj = new Date(date);\r\n dateObj.setHours(0, 0, 0, 0);\r\n return dateObj;\r\n};\r\n\r\n/**\r\n * Get end of day\r\n */\r\nexport const endOfDay = (date: Date | string | number): Date => {\r\n const dateObj = new Date(date);\r\n dateObj.setHours(23, 59, 59, 999);\r\n return dateObj;\r\n};\r\n\r\nexport default {\r\n formatDate,\r\n formatDateTime,\r\n formatRelativeTime,\r\n formatDateForInput,\r\n formatDateTimeForInput,\r\n isToday,\r\n isPast,\r\n isFuture,\r\n addDays,\r\n startOfDay,\r\n endOfDay,\r\n};\r\n","/**\r\n * Copy text to clipboard\r\n * @returns Promise<boolean> - true if successful\r\n */\r\nexport const copyToClipboard = async (text: string): Promise<boolean> => {\r\n try {\r\n // Modern API (preferred)\r\n if (navigator.clipboard && window.isSecureContext) {\r\n await navigator.clipboard.writeText(text);\r\n return true;\r\n }\r\n\r\n // Fallback for older browsers or non-secure contexts\r\n const textArea = document.createElement('textarea');\r\n textArea.value = text;\r\n textArea.style.position = 'fixed';\r\n textArea.style.left = '-999999px';\r\n textArea.style.top = '-999999px';\r\n document.body.appendChild(textArea);\r\n textArea.focus();\r\n textArea.select();\r\n\r\n const success = document.execCommand('copy');\r\n document.body.removeChild(textArea);\r\n return success;\r\n } catch (error) {\r\n console.error('Failed to copy to clipboard:', error);\r\n return false;\r\n }\r\n};\r\n\r\n/**\r\n * Read text from clipboard\r\n * @returns Promise<string | null>\r\n */\r\nexport const readFromClipboard = async (): Promise<string | null> => {\r\n try {\r\n if (navigator.clipboard && window.isSecureContext) {\r\n return await navigator.clipboard.readText();\r\n }\r\n return null;\r\n } catch (error) {\r\n console.error('Failed to read from clipboard:', error);\r\n return null;\r\n }\r\n};\r\n\r\n/**\r\n * Check if clipboard API is available\r\n */\r\nexport const isClipboardAvailable = (): boolean => {\r\n return !!(navigator.clipboard && window.isSecureContext);\r\n};\r\n\r\nexport default {\r\n copyToClipboard,\r\n readFromClipboard,\r\n isClipboardAvailable,\r\n};\r\n","/**\r\n * Generate URL-friendly slug from text\r\n */\r\nexport const slugify = (text: string): string => {\r\n return text\r\n .toString()\r\n .toLowerCase()\r\n .trim()\r\n .replace(/\\s+/g, '-') // Replace spaces with -\r\n .replace(/[^\\w\\-]+/g, '') // Remove non-word chars\r\n .replace(/\\-\\-+/g, '-') // Replace multiple - with single -\r\n .replace(/^-+/, '') // Trim - from start\r\n .replace(/-+$/, ''); // Trim - from end\r\n};\r\n\r\n/**\r\n * Generate slug with unique suffix\r\n */\r\nexport const slugifyUnique = (text: string): string => {\r\n const baseSlug = slugify(text);\r\n const uniqueSuffix = Date.now().toString(36) + Math.random().toString(36).substring(2, 5);\r\n return `${baseSlug}-${uniqueSuffix}`;\r\n};\r\n\r\n/**\r\n * Convert slug back to readable text\r\n */\r\nexport const unslugify = (slug: string): string => {\r\n return slug\r\n .replace(/-/g, ' ')\r\n .replace(/\\b\\w/g, (char) => char.toUpperCase());\r\n};\r\n\r\n/**\r\n * Truncate text to specified length with ellipsis\r\n */\r\nexport const truncate = (\r\n text: string,\r\n maxLength: number,\r\n suffix: string = '...'\r\n): string => {\r\n if (text.length <= maxLength) return text;\r\n return text.substring(0, maxLength - suffix.length).trim() + suffix;\r\n};\r\n\r\n/**\r\n * Truncate text by words\r\n */\r\nexport const truncateWords = (\r\n text: string,\r\n maxWords: number,\r\n suffix: string = '...'\r\n): string => {\r\n const words = text.split(/\\s+/);\r\n if (words.length <= maxWords) return text;\r\n return words.slice(0, maxWords).join(' ') + suffix;\r\n};\r\n\r\n/**\r\n * Capitalize first letter of each word\r\n */\r\nexport const capitalizeWords = (text: string): string => {\r\n return text.replace(/\\b\\w/g, (char) => char.toUpperCase());\r\n};\r\n\r\n/**\r\n * Capitalize first letter only\r\n */\r\nexport const capitalize = (text: string): string => {\r\n if (!text) return '';\r\n return text.charAt(0).toUpperCase() + text.slice(1);\r\n};\r\n\r\n/**\r\n * Convert camelCase to kebab-case\r\n */\r\nexport const camelToKebab = (text: string): string => {\r\n return text.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\r\n};\r\n\r\n/**\r\n * Convert kebab-case to camelCase\r\n */\r\nexport const kebabToCamel = (text: string): string => {\r\n return text.replace(/-([a-z])/g, (_, char) => char.toUpperCase());\r\n};\r\n\r\nexport default {\r\n slugify,\r\n slugifyUnique,\r\n unslugify,\r\n truncate,\r\n truncateWords,\r\n capitalizeWords,\r\n capitalize,\r\n camelToKebab,\r\n kebabToCamel,\r\n};\r\n","/**\r\n * Event Emitter for client-side event handling\r\n */\r\n\r\ntype EventHandler<T = unknown> = (data: T) => void;\r\n\r\ninterface EventMap {\r\n [event: string]: unknown;\r\n}\r\n\r\n/**\r\n * Simple typed event emitter for browser use\r\n */\r\nexport class EventEmitter<Events extends EventMap = EventMap> {\r\n private handlers: Map<keyof Events, Set<EventHandler<unknown>>> = new Map();\r\n\r\n /**\r\n * Subscribe to an event\r\n * @returns Unsubscribe function\r\n */\r\n on<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): () => void {\r\n if (!this.handlers.has(event)) {\r\n this.handlers.set(event, new Set());\r\n }\r\n this.handlers.get(event)!.add(handler as EventHandler<unknown>);\r\n\r\n // Return unsubscribe function\r\n return () => this.off(event, handler);\r\n }\r\n\r\n /**\r\n * Subscribe to an event once\r\n */\r\n once<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): () => void {\r\n const wrappedHandler: EventHandler<Events[K]> = (data) => {\r\n this.off(event, wrappedHandler);\r\n handler(data);\r\n };\r\n return this.on(event, wrappedHandler);\r\n }\r\n\r\n /**\r\n * Unsubscribe from an event\r\n */\r\n off<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): void {\r\n const eventHandlers = this.handlers.get(event);\r\n if (eventHandlers) {\r\n eventHandlers.delete(handler as EventHandler<unknown>);\r\n }\r\n }\r\n\r\n /**\r\n * Emit an event\r\n */\r\n emit<K extends keyof Events>(event: K, data: Events[K]): void {\r\n const eventHandlers = this.handlers.get(event);\r\n if (eventHandlers) {\r\n eventHandlers.forEach((handler) => {\r\n try {\r\n handler(data);\r\n } catch (error) {\r\n console.error(`Error in event handler for \"${String(event)}\":`, error);\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Remove all handlers for an event (or all events)\r\n */\r\n removeAllListeners(event?: keyof Events): void {\r\n if (event) {\r\n this.handlers.delete(event);\r\n } else {\r\n this.handlers.clear();\r\n }\r\n }\r\n\r\n /**\r\n * Get count of listeners for an event\r\n */\r\n listenerCount(event: keyof Events): number {\r\n return this.handlers.get(event)?.size ?? 0;\r\n }\r\n}\r\n\r\n/**\r\n * Create a new event emitter instance\r\n */\r\nexport const createEventEmitter = <Events extends EventMap = EventMap>(): EventEmitter<Events> => {\r\n return new EventEmitter<Events>();\r\n};\r\n\r\n/**\r\n * Global app event emitter (singleton)\r\n */\r\nexport const appEvents = new EventEmitter<{\r\n 'auth:login': { userId: string };\r\n 'auth:logout': void;\r\n 'notification:show': { message: string; type: 'success' | 'error' | 'warning' | 'info' };\r\n 'theme:change': 'light' | 'dark';\r\n [key: string]: unknown;\r\n}>();\r\n\r\nexport default {\r\n EventEmitter,\r\n createEventEmitter,\r\n appEvents,\r\n};\r\n","/**\r\n * API URL Builder\r\n * Centralized API endpoint management\r\n */\r\n\r\nexport interface ApiUrlConfig {\r\n baseUrl: string;\r\n version?: string;\r\n}\r\n\r\n/**\r\n * API URL builder class\r\n */\r\nexport class ApiUrlBuilder {\r\n private baseUrl: string;\r\n private version: string;\r\n\r\n constructor(config: ApiUrlConfig) {\r\n this.baseUrl = config.baseUrl.replace(/\\/$/, ''); // Remove trailing slash\r\n this.version = config.version || '';\r\n }\r\n\r\n /**\r\n * Build full URL from path\r\n */\r\n build(path: string): string {\r\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\r\n const versionPath = this.version ? `/${this.version}` : '';\r\n return `${this.baseUrl}${versionPath}${normalizedPath}`;\r\n }\r\n\r\n /**\r\n * Build URL with query parameters\r\n */\r\n buildWithParams(path: string, params: Record<string, string | number | boolean | undefined>): string {\r\n const url = this.build(path);\r\n const filteredParams = Object.entries(params)\r\n .filter(([, value]) => value !== undefined)\r\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)\r\n .join('&');\r\n\r\n return filteredParams ? `${url}?${filteredParams}` : url;\r\n }\r\n\r\n /**\r\n * Build URL with path parameters\r\n */\r\n buildWithPathParams(template: string, params: Record<string, string | number>): string {\r\n let path = template;\r\n Object.entries(params).forEach(([key, value]) => {\r\n path = path.replace(`:${key}`, String(value));\r\n path = path.replace(`{${key}}`, String(value));\r\n });\r\n return this.build(path);\r\n }\r\n\r\n /**\r\n * Get base URL\r\n */\r\n getBaseUrl(): string {\r\n return this.baseUrl;\r\n }\r\n\r\n /**\r\n * Set new base URL\r\n */\r\n setBaseUrl(baseUrl: string): void {\r\n this.baseUrl = baseUrl.replace(/\\/$/, '');\r\n }\r\n}\r\n\r\n/**\r\n * Create API URL builder\r\n */\r\nexport const createApiUrlBuilder = (config: ApiUrlConfig): ApiUrlBuilder => {\r\n return new ApiUrlBuilder(config);\r\n};\r\n\r\n/**\r\n * Common API endpoints factory\r\n */\r\nexport const createApiEndpoints = (builder: ApiUrlBuilder) => ({\r\n // Auth endpoints\r\n auth: {\r\n login: () => builder.build('/auth/login'),\r\n register: () => builder.build('/auth/register'),\r\n logout: () => builder.build('/auth/logout'),\r\n refresh: () => builder.build('/auth/refresh'),\r\n me: () => builder.build('/auth/me'),\r\n forgotPassword: () => builder.build('/auth/forgot-password'),\r\n resetPassword: () => builder.build('/auth/reset-password'),\r\n },\r\n\r\n // User endpoints\r\n users: {\r\n list: () => builder.build('/users'),\r\n get: (id: string) => builder.buildWithPathParams('/users/:id', { id }),\r\n create: () => builder.build('/users'),\r\n update: (id: string) => builder.buildWithPathParams('/users/:id', { id }),\r\n delete: (id: string) => builder.buildWithPathParams('/users/:id', { id }),\r\n },\r\n\r\n // Generic CRUD factory\r\n crud: (resource: string) => ({\r\n list: () => builder.build(`/${resource}`),\r\n get: (id: string) => builder.buildWithPathParams(`/${resource}/:id`, { id }),\r\n create: () => builder.build(`/${resource}`),\r\n update: (id: string) => builder.buildWithPathParams(`/${resource}/:id`, { id }),\r\n delete: (id: string) => builder.buildWithPathParams(`/${resource}/:id`, { id }),\r\n }),\r\n});\r\n\r\nexport default {\r\n ApiUrlBuilder,\r\n createApiUrlBuilder,\r\n createApiEndpoints,\r\n};\r\n","/**\n * Response Parser Utilities\n * Common patterns for parsing API responses\n */\nimport type { ApiResponse, PaginatedResponse, PaginationMeta } from '../../shared/types';\n\n/**\n * Check if response is successful\n */\nexport const isSuccessResponse = <T>(response: ApiResponse<T>): response is ApiResponse<T> & { success: true } => {\n return response.success === true;\n};\n\n/**\n * Check if response is an error\n */\nexport const isErrorResponse = <T>(response: ApiResponse<T>): response is ApiResponse<T> & { success: false } => {\n return response.success === false;\n};\n\n/**\n * Extract data from response or return default\n */\nexport const getResponseData = <T>(response: ApiResponse<T>, defaultValue: T): T => {\n if (isSuccessResponse(response) && response.data !== undefined) {\n return response.data;\n }\n return defaultValue;\n};\n\n/**\n * Extract error message from response\n */\nexport const getErrorMessage = <T>(response: ApiResponse<T>, defaultMessage: string = 'An error occurred'): string => {\n if (response.error) {\n return response.error;\n }\n if (response.message) {\n return response.message;\n }\n return defaultMessage;\n};\n\n/**\n * Check if response has data\n */\nexport const hasData = <T>(response: ApiResponse<T>): response is ApiResponse<T> & { data: NonNullable<T> } => {\n return response.data !== null && response.data !== undefined;\n};\n\n/**\n * Check if paginated response has more pages\n */\nexport const hasMorePages = <T>(response: PaginatedResponse<T>): boolean => {\n return response.pagination.hasNextPage;\n};\n\n/**\n * Get next page number from paginated response\n */\nexport const getNextPage = <T>(response: PaginatedResponse<T>): number | null => {\n if (response.pagination.hasNextPage) {\n return response.pagination.page + 1;\n }\n return null;\n};\n\n/**\n * Get previous page number from paginated response\n */\nexport const getPrevPage = <T>(response: PaginatedResponse<T>): number | null => {\n if (response.pagination.hasPrevPage) {\n return response.pagination.page - 1;\n }\n return null;\n};\n\n/**\n * Create empty pagination meta\n */\nexport const createEmptyPaginationMeta = (): PaginationMeta => ({\n total: 0,\n page: 1,\n limit: 10,\n totalPages: 0,\n hasNextPage: false,\n hasPrevPage: false,\n});\n\n/**\n * Create success response\n */\nexport const createSuccessResponse = <T>(data: T, message: string = 'Success'): ApiResponse<T> => ({\n success: true,\n message,\n data,\n statusCode: 200,\n});\n\n/**\n * Create error response\n */\nexport const createErrorResponse = (\n message: string,\n statusCode: number = 400,\n error?: string\n): ApiResponse<never> => ({\n success: false,\n message,\n error,\n statusCode,\n});\n\nexport default {\n isSuccessResponse,\n isErrorResponse,\n getResponseData,\n getErrorMessage,\n hasData,\n hasMorePages,\n getNextPage,\n getPrevPage,\n createEmptyPaginationMeta,\n createSuccessResponse,\n createErrorResponse,\n};\n","/**\r\n * useLocalStorage Hook\r\n * Syncs state with localStorage, supports cross-tab synchronization\r\n */\r\nimport { useState, useEffect, useCallback } from 'react';\r\n\r\nexport type SetValue<T> = T | ((prevValue: T) => T);\r\n\r\nexport interface UseLocalStorageOptions<T> {\r\n /** Serialize function (default: JSON.stringify) */\r\n serializer?: (value: T) => string;\r\n /** Deserialize function (default: JSON.parse) */\r\n deserializer?: (value: string) => T;\r\n /** Enable cross-tab synchronization (default: true) */\r\n syncTabs?: boolean;\r\n /** Enable logging (default: false) */\r\n debug?: boolean;\r\n}\r\n\r\n/**\r\n * Hook to persist state in localStorage with cross-tab sync\r\n * @param key - localStorage key\r\n * @param initialValue - initial/fallback value\r\n * @param options - configuration options\r\n */\r\nexport function useLocalStorage<T>(\r\n key: string,\r\n initialValue: T,\r\n options: UseLocalStorageOptions<T> = {}\r\n): [T, (value: SetValue<T>) => void, () => void] {\r\n const {\r\n serializer = JSON.stringify,\r\n deserializer = JSON.parse,\r\n syncTabs = true,\r\n debug = false,\r\n } = options;\r\n\r\n const log = useCallback(\r\n (...args: unknown[]) => {\r\n if (debug) console.log(`[useLocalStorage:${key}]`, ...args);\r\n },\r\n [debug, key]\r\n );\r\n\r\n // Get initial value from localStorage or use initialValue\r\n const readValue = useCallback((): T => {\r\n if (typeof window === 'undefined') {\r\n return initialValue;\r\n }\r\n\r\n try {\r\n const item = window.localStorage.getItem(key);\r\n if (item === null) {\r\n return initialValue;\r\n }\r\n const parsed = deserializer(item);\r\n log('Read value:', parsed);\r\n return parsed;\r\n } catch (error) {\r\n console.warn(`Error reading localStorage key \"${key}\":`, error);\r\n return initialValue;\r\n }\r\n }, [key, initialValue, deserializer, log]);\r\n\r\n const [storedValue, setStoredValue] = useState<T>(readValue);\r\n\r\n // Return a wrapped version of useState's setter function\r\n const setValue = useCallback(\r\n (value: SetValue<T>) => {\r\n if (typeof window === 'undefined') {\r\n console.warn(`Cannot set localStorage key \"${key}\" in non-browser environment`);\r\n return;\r\n }\r\n\r\n try {\r\n // Allow value to be a function (same API as useState)\r\n const valueToStore = value instanceof Function ? value(storedValue) : value;\r\n\r\n setStoredValue(valueToStore);\r\n window.localStorage.setItem(key, serializer(valueToStore));\r\n log('Set value:', valueToStore);\r\n\r\n // Dispatch storage event for cross-tab sync (same tab doesn't receive storage events)\r\n window.dispatchEvent(new StorageEvent('storage', { key, newValue: serializer(valueToStore) }));\r\n } catch (error) {\r\n console.warn(`Error setting localStorage key \"${key}\":`, error);\r\n }\r\n },\r\n [key, storedValue, serializer, log]\r\n );\r\n\r\n // Remove value from localStorage\r\n const removeValue = useCallback(() => {\r\n if (typeof window === 'undefined') {\r\n return;\r\n }\r\n\r\n try {\r\n window.localStorage.removeItem(key);\r\n setStoredValue(initialValue);\r\n log('Removed value');\r\n\r\n window.dispatchEvent(new StorageEvent('storage', { key, newValue: null }));\r\n } catch (error) {\r\n console.warn(`Error removing localStorage key \"${key}\":`, error);\r\n }\r\n }, [key, initialValue, log]);\r\n\r\n // Cross-tab synchronization\r\n useEffect(() => {\r\n if (!syncTabs || typeof window === 'undefined') {\r\n return;\r\n }\r\n\r\n const handleStorageChange = (event: StorageEvent) => {\r\n if (event.key !== key) {\r\n return;\r\n }\r\n\r\n log('Storage event received:', event.newValue);\r\n\r\n if (event.newValue === null) {\r\n setStoredValue(initialValue);\r\n } else {\r\n try {\r\n setStoredValue(deserializer(event.newValue));\r\n } catch {\r\n console.warn(`Error parsing localStorage change for key \"${key}\"`);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('storage', handleStorageChange);\r\n return () => window.removeEventListener('storage', handleStorageChange);\r\n }, [key, initialValue, syncTabs, deserializer, log]);\r\n\r\n return [storedValue, setValue, removeValue];\r\n}\r\n\r\nexport default useLocalStorage;\r\n","/**\r\n * useDebounce Hook\r\n * Returns a debounced version of the value that only updates after delay\r\n */\r\nimport { useState, useEffect } from 'react';\r\n\r\n/**\r\n * Debounce a value with configurable delay\r\n * @param value - Value to debounce\r\n * @param delay - Delay in milliseconds (default: 500)\r\n */\r\nexport function useDebounce<T>(value: T, delay: number = 500): T {\r\n const [debouncedValue, setDebouncedValue] = useState<T>(value);\r\n\r\n useEffect(() => {\r\n const timer = setTimeout(() => {\r\n setDebouncedValue(value);\r\n }, delay);\r\n\r\n return () => {\r\n clearTimeout(timer);\r\n };\r\n }, [value, delay]);\r\n\r\n return debouncedValue;\r\n}\r\n\r\nexport default useDebounce;\r\n","/**\r\n * useCopyToClipboard Hook\r\n * Copy text to clipboard with status tracking\r\n */\r\nimport { useState, useCallback } from 'react';\r\n\r\nexport interface UseCopyToClipboardReturn {\r\n /** Copy text to clipboard */\r\n copy: (text: string) => Promise<boolean>;\r\n /** Whether copy was successful (resets after timeout) */\r\n copied: boolean;\r\n /** Error message if copy failed */\r\n error: string | null;\r\n /** Reset state */\r\n reset: () => void;\r\n}\r\n\r\n/**\r\n * Copy text to clipboard with feedback\r\n * @param resetDelay - Time in ms before copied state resets (default: 2000)\r\n */\r\nexport function useCopyToClipboard(resetDelay: number = 2000): UseCopyToClipboardReturn {\r\n const [copied, setCopied] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const reset = useCallback(() => {\r\n setCopied(false);\r\n setError(null);\r\n }, []);\r\n\r\n const copy = useCallback(\r\n async (text: string): Promise<boolean> => {\r\n if (!navigator?.clipboard) {\r\n // Fallback for older browsers\r\n try {\r\n const textarea = document.createElement('textarea');\r\n textarea.value = text;\r\n textarea.style.position = 'fixed';\r\n textarea.style.left = '-999999px';\r\n textarea.style.top = '-999999px';\r\n document.body.appendChild(textarea);\r\n textarea.focus();\r\n textarea.select();\r\n\r\n const successful = document.execCommand('copy');\r\n document.body.removeChild(textarea);\r\n\r\n if (successful) {\r\n setCopied(true);\r\n setError(null);\r\n setTimeout(reset, resetDelay);\r\n return true;\r\n } else {\r\n throw new Error('execCommand failed');\r\n }\r\n } catch (err) {\r\n const message = err instanceof Error ? err.message : 'Failed to copy to clipboard';\r\n setError(message);\r\n setCopied(false);\r\n return false;\r\n }\r\n }\r\n\r\n try {\r\n await navigator.clipboard.writeText(text);\r\n setCopied(true);\r\n setError(null);\r\n setTimeout(reset, resetDelay);\r\n return true;\r\n } catch (err) {\r\n const message = err instanceof Error ? err.message : 'Failed to copy to clipboard';\r\n setError(message);\r\n setCopied(false);\r\n return false;\r\n }\r\n },\r\n [resetDelay, reset]\r\n );\r\n\r\n return { copy, copied, error, reset };\r\n}\r\n\r\nexport default useCopyToClipboard;\r\n","/**\r\n * usePageTitle Hook\r\n * Dynamically set the document title\r\n */\r\nimport { useEffect } from 'react';\r\n\r\nexport interface UsePageTitleOptions {\r\n /** Suffix to append to the title (e.g., organization name) */\r\n suffix?: string;\r\n /** Separator between title and suffix (default: ' | ') */\r\n separator?: string;\r\n /** Whether to restore original title on unmount (default: true) */\r\n restoreOnUnmount?: boolean;\r\n}\r\n\r\n/**\r\n * Set the document title with optional suffix\r\n * @param title - Page title\r\n * @param options - Configuration options\r\n */\r\nexport function usePageTitle(title: string, options: UsePageTitleOptions = {}): void {\r\n const { suffix, separator = ' | ', restoreOnUnmount = true } = options;\r\n\r\n useEffect(() => {\r\n const originalTitle = document.title;\r\n const newTitle = suffix ? `${title}${separator}${suffix}` : title;\r\n document.title = newTitle;\r\n\r\n return () => {\r\n if (restoreOnUnmount) {\r\n document.title = originalTitle;\r\n }\r\n };\r\n }, [title, suffix, separator, restoreOnUnmount]);\r\n}\r\n\r\nexport default usePageTitle;\r\n","/**\r\n * useInterval Hook\r\n * Set up a recurring interval that properly cleans up\r\n */\r\nimport { useEffect, useRef } from 'react';\r\n\r\n/**\r\n * Run a callback on an interval\r\n * @param callback - Function to call on each interval\r\n * @param delay - Interval delay in ms (null to pause)\r\n */\r\nexport function useInterval(callback: () => void, delay: number | null): void {\r\n const savedCallback = useRef(callback);\r\n\r\n // Remember the latest callback\r\n useEffect(() => {\r\n savedCallback.current = callback;\r\n }, [callback]);\r\n\r\n // Set up the interval\r\n useEffect(() => {\r\n if (delay === null) {\r\n return;\r\n }\r\n\r\n const tick = () => savedCallback.current();\r\n const id = setInterval(tick, delay);\r\n\r\n return () => clearInterval(id);\r\n }, [delay]);\r\n}\r\n\r\nexport default useInterval;\r\n","/**\r\n * useThemeDetector Hook\r\n * Detect system color scheme (light/dark mode)\r\n */\r\nimport { useState, useEffect } from 'react';\r\n\r\nexport type ThemeMode = 'light' | 'dark';\r\n\r\n/**\r\n * Detect and track system color scheme preference\r\n * @returns Current theme mode based on system preference\r\n */\r\nexport function useThemeDetector(): ThemeMode {\r\n const getCurrentTheme = (): ThemeMode => {\r\n if (typeof window === 'undefined') return 'light';\r\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\r\n };\r\n\r\n const [theme, setTheme] = useState<ThemeMode>(getCurrentTheme);\r\n\r\n useEffect(() => {\r\n if (typeof window === 'undefined') return;\r\n\r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n const handleChange = (e: MediaQueryListEvent) => {\r\n setTheme(e.matches ? 'dark' : 'light');\r\n };\r\n\r\n mediaQuery.addEventListener('change', handleChange);\r\n return () => mediaQuery.removeEventListener('change', handleChange);\r\n }, []);\r\n\r\n return theme;\r\n}\r\n\r\nexport default useThemeDetector;\r\n","/**\r\n * useSnackbar Hook\r\n * Show toast/snackbar notifications\r\n */\r\nimport { useState, useCallback } from 'react';\r\n\r\nexport type SnackbarSeverity = 'success' | 'error' | 'warning' | 'info';\r\n\r\nexport interface SnackbarState {\r\n open: boolean;\r\n message: string;\r\n severity: SnackbarSeverity;\r\n autoHideDuration?: number;\r\n}\r\n\r\nexport interface UseSnackbarReturn {\r\n /** Current snackbar state */\r\n state: SnackbarState;\r\n /** Show snackbar with message */\r\n show: (message: string, severity?: SnackbarSeverity, duration?: number) => void;\r\n /** Show success snackbar */\r\n success: (message: string, duration?: number) => void;\r\n /** Show error snackbar */\r\n error: (message: string, duration?: number) => void;\r\n /** Show warning snackbar */\r\n warning: (message: string, duration?: number) => void;\r\n /** Show info snackbar */\r\n info: (message: string, duration?: number) => void;\r\n /** Close snackbar */\r\n close: () => void;\r\n}\r\n\r\nconst DEFAULT_DURATION = 4000;\r\n\r\n/**\r\n * Manage snackbar/toast notification state\r\n * @param defaultDuration - Default auto-hide duration in ms\r\n */\r\nexport function useSnackbar(defaultDuration: number = DEFAULT_DURATION): UseSnackbarReturn {\r\n const [state, setState] = useState<SnackbarState>({\r\n open: false,\r\n message: '',\r\n severity: 'info',\r\n autoHideDuration: defaultDuration,\r\n });\r\n\r\n const show = useCallback(\r\n (message: string, severity: SnackbarSeverity = 'info', duration?: number) => {\r\n setState({\r\n open: true,\r\n message,\r\n severity,\r\n autoHideDuration: duration ?? defaultDuration,\r\n });\r\n },\r\n [defaultDuration]\r\n );\r\n\r\n const success = useCallback(\r\n (message: string, duration?: number) => show(message, 'success', duration),\r\n [show]\r\n );\r\n\r\n const error = useCallback(\r\n (message: string, duration?: number) => show(message, 'error', duration),\r\n [show]\r\n );\r\n\r\n const warning = useCallback(\r\n (message: string, duration?: number) => show(message, 'warning', duration),\r\n [show]\r\n );\r\n\r\n const info = useCallback(\r\n (message: string, duration?: number) => show(message, 'info', duration),\r\n [show]\r\n );\r\n\r\n const close = useCallback(() => {\r\n setState((prev) => ({ ...prev, open: false }));\r\n }, []);\r\n\r\n return { state, show, success, error, warning, info, close };\r\n}\r\n\r\nexport default useSnackbar;\r\n","/**\r\n * useMediaQuery Hook\r\n * Track media query matches\r\n */\r\nimport { useState, useEffect } from 'react';\r\n\r\n/**\r\n * Track a media query match\r\n * @param query - CSS media query string (e.g., '(min-width: 768px)')\r\n */\r\nexport function useMediaQuery(query: string): boolean {\r\n const getMatches = (query: string): boolean => {\r\n if (typeof window === 'undefined') return false;\r\n return window.matchMedia(query).matches;\r\n };\r\n\r\n const [matches, setMatches] = useState<boolean>(getMatches(query));\r\n\r\n useEffect(() => {\r\n if (typeof window === 'undefined') return;\r\n\r\n const mediaQuery = window.matchMedia(query);\r\n const handleChange = () => setMatches(mediaQuery.matches);\r\n\r\n // Set initial value\r\n handleChange();\r\n\r\n mediaQuery.addEventListener('change', handleChange);\r\n return () => mediaQuery.removeEventListener('change', handleChange);\r\n }, [query]);\r\n\r\n return matches;\r\n}\r\n\r\n// Preset breakpoint hooks\r\nexport const useIsMobile = () => useMediaQuery('(max-width: 767px)');\r\nexport const useIsTablet = () => useMediaQuery('(min-width: 768px) and (max-width: 1023px)');\r\nexport const useIsDesktop = () => useMediaQuery('(min-width: 1024px)');\r\nexport const useIsMobileOrTablet = () => useMediaQuery('(max-width: 1023px)');\r\n\r\nexport default useMediaQuery;\r\n","/**\r\n * useOnClickOutside Hook\r\n * Detect clicks outside of a referenced element\r\n */\r\nimport { useEffect, RefObject } from 'react';\r\n\r\ntype Handler = (event: MouseEvent | TouchEvent) => void;\r\n\r\n/**\r\n * Detect clicks outside of a referenced element\r\n * @param ref - React ref to the element\r\n * @param handler - Callback when click outside occurs\r\n * @param enabled - Whether the hook is enabled (default: true)\r\n */\r\nexport function useOnClickOutside<T extends HTMLElement = HTMLElement>(\r\n ref: RefObject<T>,\r\n handler: Handler,\r\n enabled: boolean = true\r\n): void {\r\n useEffect(() => {\r\n if (!enabled) return;\r\n\r\n const listener = (event: MouseEvent | TouchEvent) => {\r\n const el = ref?.current;\r\n\r\n // Do nothing if clicking ref's element or descendent elements\r\n if (!el || el.contains(event.target as Node)) {\r\n return;\r\n }\r\n\r\n handler(event);\r\n };\r\n\r\n document.addEventListener('mousedown', listener);\r\n document.addEventListener('touchstart', listener);\r\n\r\n return () => {\r\n document.removeEventListener('mousedown', listener);\r\n document.removeEventListener('touchstart', listener);\r\n };\r\n }, [ref, handler, enabled]);\r\n}\r\n\r\nexport default useOnClickOutside;\r\n","/**\r\n * useWindowSize Hook\r\n * Track window dimensions\r\n */\r\nimport { useState, useEffect } from 'react';\r\n\r\nexport interface WindowSize {\r\n width: number;\r\n height: number;\r\n}\r\n\r\n/**\r\n * Track window dimensions with resize updates\r\n * @param debounceMs - Debounce resize events (default: 100ms)\r\n */\r\nexport function useWindowSize(debounceMs: number = 100): WindowSize {\r\n const getSize = (): WindowSize => ({\r\n width: typeof window !== 'undefined' ? window.innerWidth : 0,\r\n height: typeof window !== 'undefined' ? window.innerHeight : 0,\r\n });\r\n\r\n const [windowSize, setWindowSize] = useState<WindowSize>(getSize);\r\n\r\n useEffect(() => {\r\n if (typeof window === 'undefined') return;\r\n\r\n let timeoutId: NodeJS.Timeout;\r\n\r\n const handleResize = () => {\r\n clearTimeout(timeoutId);\r\n timeoutId = setTimeout(() => {\r\n setWindowSize(getSize());\r\n }, debounceMs);\r\n };\r\n\r\n // Set initial size\r\n setWindowSize(getSize());\r\n\r\n window.addEventListener('resize', handleResize);\r\n return () => {\r\n clearTimeout(timeoutId);\r\n window.removeEventListener('resize', handleResize);\r\n };\r\n }, [debounceMs]);\r\n\r\n return windowSize;\r\n}\r\n\r\nexport default useWindowSize;\r\n"]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Levels
|
|
3
|
+
*/
|
|
4
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
5
|
+
/**
|
|
6
|
+
* Client Logger Configuration
|
|
7
|
+
*/
|
|
8
|
+
interface ClientLoggerConfig {
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
minLevel?: LogLevel;
|
|
11
|
+
prefix?: string;
|
|
12
|
+
includeTimestamp?: boolean;
|
|
13
|
+
remoteLogging?: {
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
endpoint: string;
|
|
16
|
+
batchSize?: number;
|
|
17
|
+
flushInterval?: number;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Client-side logger with optional remote logging
|
|
22
|
+
*/
|
|
23
|
+
declare class ClientLogger {
|
|
24
|
+
private config;
|
|
25
|
+
private buffer;
|
|
26
|
+
private flushTimer?;
|
|
27
|
+
constructor(config?: ClientLoggerConfig);
|
|
28
|
+
private shouldLog;
|
|
29
|
+
private formatMessage;
|
|
30
|
+
private log;
|
|
31
|
+
debug(message: string, data?: unknown): void;
|
|
32
|
+
info(message: string, data?: unknown): void;
|
|
33
|
+
warn(message: string, data?: unknown): void;
|
|
34
|
+
error(message: string, data?: unknown): void;
|
|
35
|
+
/**
|
|
36
|
+
* Flush buffered logs to remote endpoint
|
|
37
|
+
*/
|
|
38
|
+
flush(): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Cleanup logger (clear intervals)
|
|
41
|
+
*/
|
|
42
|
+
destroy(): void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a new logger instance
|
|
46
|
+
*/
|
|
47
|
+
declare const createClientLogger: (config?: ClientLoggerConfig) => ClientLogger;
|
|
48
|
+
/**
|
|
49
|
+
* Default logger instance
|
|
50
|
+
*/
|
|
51
|
+
declare const clientLogger: ClientLogger;
|
|
52
|
+
|
|
53
|
+
export { ClientLogger, type ClientLoggerConfig, type LogLevel, clientLogger, createClientLogger };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log Levels
|
|
3
|
+
*/
|
|
4
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
5
|
+
/**
|
|
6
|
+
* Client Logger Configuration
|
|
7
|
+
*/
|
|
8
|
+
interface ClientLoggerConfig {
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
minLevel?: LogLevel;
|
|
11
|
+
prefix?: string;
|
|
12
|
+
includeTimestamp?: boolean;
|
|
13
|
+
remoteLogging?: {
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
endpoint: string;
|
|
16
|
+
batchSize?: number;
|
|
17
|
+
flushInterval?: number;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Client-side logger with optional remote logging
|
|
22
|
+
*/
|
|
23
|
+
declare class ClientLogger {
|
|
24
|
+
private config;
|
|
25
|
+
private buffer;
|
|
26
|
+
private flushTimer?;
|
|
27
|
+
constructor(config?: ClientLoggerConfig);
|
|
28
|
+
private shouldLog;
|
|
29
|
+
private formatMessage;
|
|
30
|
+
private log;
|
|
31
|
+
debug(message: string, data?: unknown): void;
|
|
32
|
+
info(message: string, data?: unknown): void;
|
|
33
|
+
warn(message: string, data?: unknown): void;
|
|
34
|
+
error(message: string, data?: unknown): void;
|
|
35
|
+
/**
|
|
36
|
+
* Flush buffered logs to remote endpoint
|
|
37
|
+
*/
|
|
38
|
+
flush(): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Cleanup logger (clear intervals)
|
|
41
|
+
*/
|
|
42
|
+
destroy(): void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a new logger instance
|
|
46
|
+
*/
|
|
47
|
+
declare const createClientLogger: (config?: ClientLoggerConfig) => ClientLogger;
|
|
48
|
+
/**
|
|
49
|
+
* Default logger instance
|
|
50
|
+
*/
|
|
51
|
+
declare const clientLogger: ClientLogger;
|
|
52
|
+
|
|
53
|
+
export { ClientLogger, type ClientLoggerConfig, type LogLevel, clientLogger, createClientLogger };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/client/logger/client-logger.ts
|
|
4
|
+
var LOG_LEVELS = {
|
|
5
|
+
debug: 0,
|
|
6
|
+
info: 1,
|
|
7
|
+
warn: 2,
|
|
8
|
+
error: 3
|
|
9
|
+
};
|
|
10
|
+
var ClientLogger = class {
|
|
11
|
+
constructor(config = {}) {
|
|
12
|
+
this.buffer = [];
|
|
13
|
+
this.config = {
|
|
14
|
+
enabled: config.enabled ?? process.env.NODE_ENV !== "production",
|
|
15
|
+
minLevel: config.minLevel ?? "debug",
|
|
16
|
+
prefix: config.prefix ?? "[App]",
|
|
17
|
+
includeTimestamp: config.includeTimestamp ?? true,
|
|
18
|
+
remoteLogging: config.remoteLogging
|
|
19
|
+
};
|
|
20
|
+
if (this.config.remoteLogging?.enabled) {
|
|
21
|
+
const interval = this.config.remoteLogging.flushInterval ?? 3e4;
|
|
22
|
+
this.flushTimer = setInterval(() => this.flush(), interval);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
shouldLog(level) {
|
|
26
|
+
if (!this.config.enabled) return false;
|
|
27
|
+
return LOG_LEVELS[level] >= LOG_LEVELS[this.config.minLevel];
|
|
28
|
+
}
|
|
29
|
+
formatMessage(level, message) {
|
|
30
|
+
const parts = [];
|
|
31
|
+
if (this.config.includeTimestamp) {
|
|
32
|
+
parts.push(`[${(/* @__PURE__ */ new Date()).toISOString()}]`);
|
|
33
|
+
}
|
|
34
|
+
parts.push(this.config.prefix);
|
|
35
|
+
parts.push(`[${level.toUpperCase()}]`);
|
|
36
|
+
parts.push(message);
|
|
37
|
+
return parts.join(" ");
|
|
38
|
+
}
|
|
39
|
+
log(level, message, data) {
|
|
40
|
+
if (!this.shouldLog(level)) return;
|
|
41
|
+
const formattedMessage = this.formatMessage(level, message);
|
|
42
|
+
const entry = {
|
|
43
|
+
level,
|
|
44
|
+
message,
|
|
45
|
+
data,
|
|
46
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
47
|
+
prefix: this.config.prefix
|
|
48
|
+
};
|
|
49
|
+
switch (level) {
|
|
50
|
+
case "debug":
|
|
51
|
+
console.debug(formattedMessage, data ?? "");
|
|
52
|
+
break;
|
|
53
|
+
case "info":
|
|
54
|
+
console.info(formattedMessage, data ?? "");
|
|
55
|
+
break;
|
|
56
|
+
case "warn":
|
|
57
|
+
console.warn(formattedMessage, data ?? "");
|
|
58
|
+
break;
|
|
59
|
+
case "error":
|
|
60
|
+
console.error(formattedMessage, data ?? "");
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
if (this.config.remoteLogging?.enabled) {
|
|
64
|
+
this.buffer.push(entry);
|
|
65
|
+
const batchSize = this.config.remoteLogging.batchSize ?? 10;
|
|
66
|
+
if (this.buffer.length >= batchSize) {
|
|
67
|
+
this.flush();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
debug(message, data) {
|
|
72
|
+
this.log("debug", message, data);
|
|
73
|
+
}
|
|
74
|
+
info(message, data) {
|
|
75
|
+
this.log("info", message, data);
|
|
76
|
+
}
|
|
77
|
+
warn(message, data) {
|
|
78
|
+
this.log("warn", message, data);
|
|
79
|
+
}
|
|
80
|
+
error(message, data) {
|
|
81
|
+
this.log("error", message, data);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Flush buffered logs to remote endpoint
|
|
85
|
+
*/
|
|
86
|
+
async flush() {
|
|
87
|
+
if (!this.config.remoteLogging?.enabled || this.buffer.length === 0) return;
|
|
88
|
+
const logs = [...this.buffer];
|
|
89
|
+
this.buffer = [];
|
|
90
|
+
try {
|
|
91
|
+
await fetch(this.config.remoteLogging.endpoint, {
|
|
92
|
+
method: "POST",
|
|
93
|
+
headers: { "Content-Type": "application/json" },
|
|
94
|
+
body: JSON.stringify({ logs })
|
|
95
|
+
});
|
|
96
|
+
} catch (error) {
|
|
97
|
+
this.buffer = [...logs, ...this.buffer].slice(0, 100);
|
|
98
|
+
console.error("Failed to send logs to remote endpoint", error);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Cleanup logger (clear intervals)
|
|
103
|
+
*/
|
|
104
|
+
destroy() {
|
|
105
|
+
if (this.flushTimer) {
|
|
106
|
+
clearInterval(this.flushTimer);
|
|
107
|
+
}
|
|
108
|
+
this.flush();
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
var createClientLogger = (config) => {
|
|
112
|
+
return new ClientLogger(config);
|
|
113
|
+
};
|
|
114
|
+
var clientLogger = new ClientLogger();
|
|
115
|
+
|
|
116
|
+
exports.ClientLogger = ClientLogger;
|
|
117
|
+
exports.clientLogger = clientLogger;
|
|
118
|
+
exports.createClientLogger = createClientLogger;
|
|
119
|
+
//# sourceMappingURL=index.js.map
|
|
120
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/client/logger/client-logger.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Log Levels\r\n */\r\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\r\n\r\n/**\r\n * Client Logger Configuration\r\n */\r\nexport interface ClientLoggerConfig {\r\n enabled?: boolean;\r\n minLevel?: LogLevel;\r\n prefix?: string;\r\n includeTimestamp?: boolean;\r\n remoteLogging?: {\r\n enabled: boolean;\r\n endpoint: string;\r\n batchSize?: number;\r\n flushInterval?: number;\r\n };\r\n}\r\n\r\n/**\r\n * Log Entry\r\n */\r\ninterface LogEntry {\r\n level: LogLevel;\r\n message: string;\r\n data?: unknown;\r\n timestamp: string;\r\n prefix?: string;\r\n}\r\n\r\nconst LOG_LEVELS: Record<LogLevel, number> = {\r\n debug: 0,\r\n info: 1,\r\n warn: 2,\r\n error: 3,\r\n};\r\n\r\n/**\r\n * Client-side logger with optional remote logging\r\n */\r\nexport class ClientLogger {\r\n private config: Required<Omit<ClientLoggerConfig, 'remoteLogging'>> & {\r\n remoteLogging?: ClientLoggerConfig['remoteLogging'];\r\n };\r\n private buffer: LogEntry[] = [];\r\n private flushTimer?: ReturnType<typeof setInterval>;\r\n\r\n constructor(config: ClientLoggerConfig = {}) {\r\n this.config = {\r\n enabled: config.enabled ?? (process.env.NODE_ENV !== 'production'),\r\n minLevel: config.minLevel ?? 'debug',\r\n prefix: config.prefix ?? '[App]',\r\n includeTimestamp: config.includeTimestamp ?? true,\r\n remoteLogging: config.remoteLogging,\r\n };\r\n\r\n // Setup remote logging flush interval\r\n if (this.config.remoteLogging?.enabled) {\r\n const interval = this.config.remoteLogging.flushInterval ?? 30000;\r\n this.flushTimer = setInterval(() => this.flush(), interval);\r\n }\r\n }\r\n\r\n private shouldLog(level: LogLevel): boolean {\r\n if (!this.config.enabled) return false;\r\n return LOG_LEVELS[level] >= LOG_LEVELS[this.config.minLevel];\r\n }\r\n\r\n private formatMessage(level: LogLevel, message: string): string {\r\n const parts: string[] = [];\r\n \r\n if (this.config.includeTimestamp) {\r\n parts.push(`[${new Date().toISOString()}]`);\r\n }\r\n \r\n parts.push(this.config.prefix);\r\n parts.push(`[${level.toUpperCase()}]`);\r\n parts.push(message);\r\n \r\n return parts.join(' ');\r\n }\r\n\r\n private log(level: LogLevel, message: string, data?: unknown): void {\r\n if (!this.shouldLog(level)) return;\r\n\r\n const formattedMessage = this.formatMessage(level, message);\r\n const entry: LogEntry = {\r\n level,\r\n message,\r\n data,\r\n timestamp: new Date().toISOString(),\r\n prefix: this.config.prefix,\r\n };\r\n\r\n // Console output\r\n switch (level) {\r\n case 'debug':\r\n console.debug(formattedMessage, data ?? '');\r\n break;\r\n case 'info':\r\n console.info(formattedMessage, data ?? '');\r\n break;\r\n case 'warn':\r\n console.warn(formattedMessage, data ?? '');\r\n break;\r\n case 'error':\r\n console.error(formattedMessage, data ?? '');\r\n break;\r\n }\r\n\r\n // Buffer for remote logging\r\n if (this.config.remoteLogging?.enabled) {\r\n this.buffer.push(entry);\r\n const batchSize = this.config.remoteLogging.batchSize ?? 10;\r\n if (this.buffer.length >= batchSize) {\r\n this.flush();\r\n }\r\n }\r\n }\r\n\r\n debug(message: string, data?: unknown): void {\r\n this.log('debug', message, data);\r\n }\r\n\r\n info(message: string, data?: unknown): void {\r\n this.log('info', message, data);\r\n }\r\n\r\n warn(message: string, data?: unknown): void {\r\n this.log('warn', message, data);\r\n }\r\n\r\n error(message: string, data?: unknown): void {\r\n this.log('error', message, data);\r\n }\r\n\r\n /**\r\n * Flush buffered logs to remote endpoint\r\n */\r\n async flush(): Promise<void> {\r\n if (!this.config.remoteLogging?.enabled || this.buffer.length === 0) return;\r\n\r\n const logs = [...this.buffer];\r\n this.buffer = [];\r\n\r\n try {\r\n await fetch(this.config.remoteLogging.endpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ logs }),\r\n });\r\n } catch (error) {\r\n // Re-add logs to buffer on failure (but limit size)\r\n this.buffer = [...logs, ...this.buffer].slice(0, 100);\r\n console.error('Failed to send logs to remote endpoint', error);\r\n }\r\n }\r\n\r\n /**\r\n * Cleanup logger (clear intervals)\r\n */\r\n destroy(): void {\r\n if (this.flushTimer) {\r\n clearInterval(this.flushTimer);\r\n }\r\n this.flush();\r\n }\r\n}\r\n\r\n/**\r\n * Create a new logger instance\r\n */\r\nexport const createClientLogger = (config?: ClientLoggerConfig): ClientLogger => {\r\n return new ClientLogger(config);\r\n};\r\n\r\n/**\r\n * Default logger instance\r\n */\r\nexport const clientLogger = new ClientLogger();\r\n\r\nexport default clientLogger;\r\n"]}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// src/client/logger/client-logger.ts
|
|
2
|
+
var LOG_LEVELS = {
|
|
3
|
+
debug: 0,
|
|
4
|
+
info: 1,
|
|
5
|
+
warn: 2,
|
|
6
|
+
error: 3
|
|
7
|
+
};
|
|
8
|
+
var ClientLogger = class {
|
|
9
|
+
constructor(config = {}) {
|
|
10
|
+
this.buffer = [];
|
|
11
|
+
this.config = {
|
|
12
|
+
enabled: config.enabled ?? process.env.NODE_ENV !== "production",
|
|
13
|
+
minLevel: config.minLevel ?? "debug",
|
|
14
|
+
prefix: config.prefix ?? "[App]",
|
|
15
|
+
includeTimestamp: config.includeTimestamp ?? true,
|
|
16
|
+
remoteLogging: config.remoteLogging
|
|
17
|
+
};
|
|
18
|
+
if (this.config.remoteLogging?.enabled) {
|
|
19
|
+
const interval = this.config.remoteLogging.flushInterval ?? 3e4;
|
|
20
|
+
this.flushTimer = setInterval(() => this.flush(), interval);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
shouldLog(level) {
|
|
24
|
+
if (!this.config.enabled) return false;
|
|
25
|
+
return LOG_LEVELS[level] >= LOG_LEVELS[this.config.minLevel];
|
|
26
|
+
}
|
|
27
|
+
formatMessage(level, message) {
|
|
28
|
+
const parts = [];
|
|
29
|
+
if (this.config.includeTimestamp) {
|
|
30
|
+
parts.push(`[${(/* @__PURE__ */ new Date()).toISOString()}]`);
|
|
31
|
+
}
|
|
32
|
+
parts.push(this.config.prefix);
|
|
33
|
+
parts.push(`[${level.toUpperCase()}]`);
|
|
34
|
+
parts.push(message);
|
|
35
|
+
return parts.join(" ");
|
|
36
|
+
}
|
|
37
|
+
log(level, message, data) {
|
|
38
|
+
if (!this.shouldLog(level)) return;
|
|
39
|
+
const formattedMessage = this.formatMessage(level, message);
|
|
40
|
+
const entry = {
|
|
41
|
+
level,
|
|
42
|
+
message,
|
|
43
|
+
data,
|
|
44
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
45
|
+
prefix: this.config.prefix
|
|
46
|
+
};
|
|
47
|
+
switch (level) {
|
|
48
|
+
case "debug":
|
|
49
|
+
console.debug(formattedMessage, data ?? "");
|
|
50
|
+
break;
|
|
51
|
+
case "info":
|
|
52
|
+
console.info(formattedMessage, data ?? "");
|
|
53
|
+
break;
|
|
54
|
+
case "warn":
|
|
55
|
+
console.warn(formattedMessage, data ?? "");
|
|
56
|
+
break;
|
|
57
|
+
case "error":
|
|
58
|
+
console.error(formattedMessage, data ?? "");
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
if (this.config.remoteLogging?.enabled) {
|
|
62
|
+
this.buffer.push(entry);
|
|
63
|
+
const batchSize = this.config.remoteLogging.batchSize ?? 10;
|
|
64
|
+
if (this.buffer.length >= batchSize) {
|
|
65
|
+
this.flush();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
debug(message, data) {
|
|
70
|
+
this.log("debug", message, data);
|
|
71
|
+
}
|
|
72
|
+
info(message, data) {
|
|
73
|
+
this.log("info", message, data);
|
|
74
|
+
}
|
|
75
|
+
warn(message, data) {
|
|
76
|
+
this.log("warn", message, data);
|
|
77
|
+
}
|
|
78
|
+
error(message, data) {
|
|
79
|
+
this.log("error", message, data);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Flush buffered logs to remote endpoint
|
|
83
|
+
*/
|
|
84
|
+
async flush() {
|
|
85
|
+
if (!this.config.remoteLogging?.enabled || this.buffer.length === 0) return;
|
|
86
|
+
const logs = [...this.buffer];
|
|
87
|
+
this.buffer = [];
|
|
88
|
+
try {
|
|
89
|
+
await fetch(this.config.remoteLogging.endpoint, {
|
|
90
|
+
method: "POST",
|
|
91
|
+
headers: { "Content-Type": "application/json" },
|
|
92
|
+
body: JSON.stringify({ logs })
|
|
93
|
+
});
|
|
94
|
+
} catch (error) {
|
|
95
|
+
this.buffer = [...logs, ...this.buffer].slice(0, 100);
|
|
96
|
+
console.error("Failed to send logs to remote endpoint", error);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Cleanup logger (clear intervals)
|
|
101
|
+
*/
|
|
102
|
+
destroy() {
|
|
103
|
+
if (this.flushTimer) {
|
|
104
|
+
clearInterval(this.flushTimer);
|
|
105
|
+
}
|
|
106
|
+
this.flush();
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
var createClientLogger = (config) => {
|
|
110
|
+
return new ClientLogger(config);
|
|
111
|
+
};
|
|
112
|
+
var clientLogger = new ClientLogger();
|
|
113
|
+
|
|
114
|
+
export { ClientLogger, clientLogger, createClientLogger };
|
|
115
|
+
//# sourceMappingURL=index.mjs.map
|
|
116
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/client/logger/client-logger.ts"],"names":[],"mappings":";AAgCA,IAAM,UAAA,GAAuC;AAAA,EAC3C,KAAA,EAAO,CAAA;AAAA,EACP,IAAA,EAAM,CAAA;AAAA,EACN,IAAA,EAAM,CAAA;AAAA,EACN,KAAA,EAAO;AACT,CAAA;AAKO,IAAM,eAAN,MAAmB;AAAA,EAOxB,WAAA,CAAY,MAAA,GAA6B,EAAC,EAAG;AAH7C,IAAA,IAAA,CAAQ,SAAqB,EAAC;AAI5B,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,OAAA,EAAS,MAAA,CAAO,OAAA,IAAY,OAAA,CAAQ,IAAI,QAAA,KAAa,YAAA;AAAA,MACrD,QAAA,EAAU,OAAO,QAAA,IAAY,OAAA;AAAA,MAC7B,MAAA,EAAQ,OAAO,MAAA,IAAU,OAAA;AAAA,MACzB,gBAAA,EAAkB,OAAO,gBAAA,IAAoB,IAAA;AAAA,MAC7C,eAAe,MAAA,CAAO;AAAA,KACxB;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,aAAA,EAAe,OAAA,EAAS;AACtC,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,MAAA,CAAO,aAAA,CAAc,aAAA,IAAiB,GAAA;AAC5D,MAAA,IAAA,CAAK,aAAa,WAAA,CAAY,MAAM,IAAA,CAAK,KAAA,IAAS,QAAQ,CAAA;AAAA,IAC5D;AAAA,EACF;AAAA,EAEQ,UAAU,KAAA,EAA0B;AAC1C,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,OAAA,EAAS,OAAO,KAAA;AACjC,IAAA,OAAO,WAAW,KAAK,CAAA,IAAK,UAAA,CAAW,IAAA,CAAK,OAAO,QAAQ,CAAA;AAAA,EAC7D;AAAA,EAEQ,aAAA,CAAc,OAAiB,OAAA,EAAyB;AAC9D,IAAA,MAAM,QAAkB,EAAC;AAEzB,IAAA,IAAI,IAAA,CAAK,OAAO,gBAAA,EAAkB;AAChC,MAAA,KAAA,CAAM,KAAK,CAAA,CAAA,EAAA,iBAAI,IAAI,MAAK,EAAE,WAAA,EAAa,CAAA,CAAA,CAAG,CAAA;AAAA,IAC5C;AAEA,IAAA,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA;AAC7B,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,CAAA,EAAI,KAAA,CAAM,WAAA,EAAa,CAAA,CAAA,CAAG,CAAA;AACrC,IAAA,KAAA,CAAM,KAAK,OAAO,CAAA;AAElB,IAAA,OAAO,KAAA,CAAM,KAAK,GAAG,CAAA;AAAA,EACvB;AAAA,EAEQ,GAAA,CAAI,KAAA,EAAiB,OAAA,EAAiB,IAAA,EAAsB;AAClE,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,EAAG;AAE5B,IAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,aAAA,CAAc,KAAA,EAAO,OAAO,CAAA;AAC1D,IAAA,MAAM,KAAA,GAAkB;AAAA,MACtB,KAAA;AAAA,MACA,OAAA;AAAA,MACA,IAAA;AAAA,MACA,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MAClC,MAAA,EAAQ,KAAK,MAAA,CAAO;AAAA,KACtB;AAGA,IAAA,QAAQ,KAAA;AAAO,MACb,KAAK,OAAA;AACH,QAAA,OAAA,CAAQ,KAAA,CAAM,gBAAA,EAAkB,IAAA,IAAQ,EAAE,CAAA;AAC1C,QAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAA,OAAA,CAAQ,IAAA,CAAK,gBAAA,EAAkB,IAAA,IAAQ,EAAE,CAAA;AACzC,QAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAA,OAAA,CAAQ,IAAA,CAAK,gBAAA,EAAkB,IAAA,IAAQ,EAAE,CAAA;AACzC,QAAA;AAAA,MACF,KAAK,OAAA;AACH,QAAA,OAAA,CAAQ,KAAA,CAAM,gBAAA,EAAkB,IAAA,IAAQ,EAAE,CAAA;AAC1C,QAAA;AAAA;AAIJ,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,aAAA,EAAe,OAAA,EAAS;AACtC,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,KAAK,CAAA;AACtB,MAAA,MAAM,SAAA,GAAY,IAAA,CAAK,MAAA,CAAO,aAAA,CAAc,SAAA,IAAa,EAAA;AACzD,MAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,IAAU,SAAA,EAAW;AACnC,QAAA,IAAA,CAAK,KAAA,EAAM;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAAA,EAEA,KAAA,CAAM,SAAiB,IAAA,EAAsB;AAC3C,IAAA,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,OAAA,EAAS,IAAI,CAAA;AAAA,EACjC;AAAA,EAEA,IAAA,CAAK,SAAiB,IAAA,EAAsB;AAC1C,IAAA,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAAA,EAChC;AAAA,EAEA,IAAA,CAAK,SAAiB,IAAA,EAAsB;AAC1C,IAAA,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAAA,EAChC;AAAA,EAEA,KAAA,CAAM,SAAiB,IAAA,EAAsB;AAC3C,IAAA,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,OAAA,EAAS,IAAI,CAAA;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,CAAC,KAAK,MAAA,CAAO,aAAA,EAAe,WAAW,IAAA,CAAK,MAAA,CAAO,WAAW,CAAA,EAAG;AAErE,IAAA,MAAM,IAAA,GAAO,CAAC,GAAG,IAAA,CAAK,MAAM,CAAA;AAC5B,IAAA,IAAA,CAAK,SAAS,EAAC;AAEf,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,aAAA,CAAc,QAAA,EAAU;AAAA,QAC9C,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,QAC9C,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,MAAM;AAAA,OAC9B,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AAEd,MAAA,IAAA,CAAK,MAAA,GAAS,CAAC,GAAG,IAAA,EAAM,GAAG,KAAK,MAAM,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA;AACpD,MAAA,OAAA,CAAQ,KAAA,CAAM,0CAA0C,KAAK,CAAA;AAAA,IAC/D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA,GAAgB;AACd,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,aAAA,CAAc,KAAK,UAAU,CAAA;AAAA,IAC/B;AACA,IAAA,IAAA,CAAK,KAAA,EAAM;AAAA,EACb;AACF;AAKO,IAAM,kBAAA,GAAqB,CAAC,MAAA,KAA8C;AAC/E,EAAA,OAAO,IAAI,aAAa,MAAM,CAAA;AAChC;AAKO,IAAM,YAAA,GAAe,IAAI,YAAA","file":"index.mjs","sourcesContent":["/**\r\n * Log Levels\r\n */\r\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\r\n\r\n/**\r\n * Client Logger Configuration\r\n */\r\nexport interface ClientLoggerConfig {\r\n enabled?: boolean;\r\n minLevel?: LogLevel;\r\n prefix?: string;\r\n includeTimestamp?: boolean;\r\n remoteLogging?: {\r\n enabled: boolean;\r\n endpoint: string;\r\n batchSize?: number;\r\n flushInterval?: number;\r\n };\r\n}\r\n\r\n/**\r\n * Log Entry\r\n */\r\ninterface LogEntry {\r\n level: LogLevel;\r\n message: string;\r\n data?: unknown;\r\n timestamp: string;\r\n prefix?: string;\r\n}\r\n\r\nconst LOG_LEVELS: Record<LogLevel, number> = {\r\n debug: 0,\r\n info: 1,\r\n warn: 2,\r\n error: 3,\r\n};\r\n\r\n/**\r\n * Client-side logger with optional remote logging\r\n */\r\nexport class ClientLogger {\r\n private config: Required<Omit<ClientLoggerConfig, 'remoteLogging'>> & {\r\n remoteLogging?: ClientLoggerConfig['remoteLogging'];\r\n };\r\n private buffer: LogEntry[] = [];\r\n private flushTimer?: ReturnType<typeof setInterval>;\r\n\r\n constructor(config: ClientLoggerConfig = {}) {\r\n this.config = {\r\n enabled: config.enabled ?? (process.env.NODE_ENV !== 'production'),\r\n minLevel: config.minLevel ?? 'debug',\r\n prefix: config.prefix ?? '[App]',\r\n includeTimestamp: config.includeTimestamp ?? true,\r\n remoteLogging: config.remoteLogging,\r\n };\r\n\r\n // Setup remote logging flush interval\r\n if (this.config.remoteLogging?.enabled) {\r\n const interval = this.config.remoteLogging.flushInterval ?? 30000;\r\n this.flushTimer = setInterval(() => this.flush(), interval);\r\n }\r\n }\r\n\r\n private shouldLog(level: LogLevel): boolean {\r\n if (!this.config.enabled) return false;\r\n return LOG_LEVELS[level] >= LOG_LEVELS[this.config.minLevel];\r\n }\r\n\r\n private formatMessage(level: LogLevel, message: string): string {\r\n const parts: string[] = [];\r\n \r\n if (this.config.includeTimestamp) {\r\n parts.push(`[${new Date().toISOString()}]`);\r\n }\r\n \r\n parts.push(this.config.prefix);\r\n parts.push(`[${level.toUpperCase()}]`);\r\n parts.push(message);\r\n \r\n return parts.join(' ');\r\n }\r\n\r\n private log(level: LogLevel, message: string, data?: unknown): void {\r\n if (!this.shouldLog(level)) return;\r\n\r\n const formattedMessage = this.formatMessage(level, message);\r\n const entry: LogEntry = {\r\n level,\r\n message,\r\n data,\r\n timestamp: new Date().toISOString(),\r\n prefix: this.config.prefix,\r\n };\r\n\r\n // Console output\r\n switch (level) {\r\n case 'debug':\r\n console.debug(formattedMessage, data ?? '');\r\n break;\r\n case 'info':\r\n console.info(formattedMessage, data ?? '');\r\n break;\r\n case 'warn':\r\n console.warn(formattedMessage, data ?? '');\r\n break;\r\n case 'error':\r\n console.error(formattedMessage, data ?? '');\r\n break;\r\n }\r\n\r\n // Buffer for remote logging\r\n if (this.config.remoteLogging?.enabled) {\r\n this.buffer.push(entry);\r\n const batchSize = this.config.remoteLogging.batchSize ?? 10;\r\n if (this.buffer.length >= batchSize) {\r\n this.flush();\r\n }\r\n }\r\n }\r\n\r\n debug(message: string, data?: unknown): void {\r\n this.log('debug', message, data);\r\n }\r\n\r\n info(message: string, data?: unknown): void {\r\n this.log('info', message, data);\r\n }\r\n\r\n warn(message: string, data?: unknown): void {\r\n this.log('warn', message, data);\r\n }\r\n\r\n error(message: string, data?: unknown): void {\r\n this.log('error', message, data);\r\n }\r\n\r\n /**\r\n * Flush buffered logs to remote endpoint\r\n */\r\n async flush(): Promise<void> {\r\n if (!this.config.remoteLogging?.enabled || this.buffer.length === 0) return;\r\n\r\n const logs = [...this.buffer];\r\n this.buffer = [];\r\n\r\n try {\r\n await fetch(this.config.remoteLogging.endpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ logs }),\r\n });\r\n } catch (error) {\r\n // Re-add logs to buffer on failure (but limit size)\r\n this.buffer = [...logs, ...this.buffer].slice(0, 100);\r\n console.error('Failed to send logs to remote endpoint', error);\r\n }\r\n }\r\n\r\n /**\r\n * Cleanup logger (clear intervals)\r\n */\r\n destroy(): void {\r\n if (this.flushTimer) {\r\n clearInterval(this.flushTimer);\r\n }\r\n this.flush();\r\n }\r\n}\r\n\r\n/**\r\n * Create a new logger instance\r\n */\r\nexport const createClientLogger = (config?: ClientLoggerConfig): ClientLogger => {\r\n return new ClientLogger(config);\r\n};\r\n\r\n/**\r\n * Default logger instance\r\n */\r\nexport const clientLogger = new ClientLogger();\r\n\r\nexport default clientLogger;\r\n"]}
|