houser-js-utils
Version:
A comprehensive collection of TypeScript utility functions for common development tasks including array manipulation, string processing, date handling, random number generation, validation, and much more.
1 lines • 13.5 kB
Source Map (JSON)
{"version":3,"file":"NetworkUtils.mjs","sources":["../src/NetworkUtils.ts"],"sourcesContent":["/**\n * @module NetworkUtils\n * @description Utility functions for network operations in the browser, including fetch helpers with authentication, caching, progress, retry, and timeout; network status listeners; and network information utilities. Designed to simplify robust HTTP requests and network state management in web applications.\n * @example\n * ```typescript\n * import { NetworkUtils } from 'houser-js-utils';\n *\n * // Add a network status listener\n * const remove = NetworkUtils.addNetworkStatusListener((online) => console.log('Online:', online));\n * // ...later\n * remove();\n *\n * // Fetch with authentication\n * const res = await NetworkUtils.fetchWithAuth('/api', 'token123');\n *\n * // Fetch with cache\n * const cachedRes = await NetworkUtils.fetchWithCache('/api/data');\n *\n * // Fetch JSON with error handling\n * const data = await NetworkUtils.fetchJson<{foo: string}>('/api/data');\n *\n * // Fetch with progress\n * await NetworkUtils.fetchWithProgress('/file', {}, (progress) => console.log('Progress:', progress));\n *\n * // Fetch with retry and timeout\n * const retryRes = await NetworkUtils.fetchWithRetry('/api', {}, 5, 500);\n * const timeoutRes = await NetworkUtils.fetchWithTimeout('/api', {}, 2000);\n *\n * // Get network speed and type\n * const speed = NetworkUtils.getNetworkSpeed();\n * const type = NetworkUtils.getNetworkType();\n *\n * // Check if online\n * if (NetworkUtils.isOnline()) {\n * // Do something when online\n * }\n * ```\n */\nexport const NetworkUtils = {\n /**\n * Adds a listener for network status changes (online/offline).\n * @param callback - Callback invoked with `true` if online, `false` if offline.\n * @returns Function to remove the listener.\n * @example\n * ```typescript\n * const remove = NetworkUtils.addNetworkStatusListener((online) => console.log('Online:', online));\n * // ...later\n * remove();\n * ```\n */\n addNetworkStatusListener: (\n callback: (online: boolean) => void\n ): (() => void) => {\n const handleOnline = () => callback(true);\n const handleOffline = () => callback(false);\n\n window.addEventListener(\"online\", handleOnline);\n window.addEventListener(\"offline\", handleOffline);\n\n return () => {\n window.removeEventListener(\"online\", handleOnline);\n window.removeEventListener(\"offline\", handleOffline);\n };\n },\n\n /**\n * Makes a fetch request with Bearer token authentication.\n * @param url - The URL to fetch.\n * @param token - The authentication token.\n * @param options - Additional fetch options.\n * @returns The fetch response.\n * @example\n * ```typescript\n * const res = await NetworkUtils.fetchWithAuth('/api', 'token123');\n * ```\n */\n fetchWithAuth: async (\n url: string,\n token: string,\n options: RequestInit = {}\n ): Promise<Response> => {\n return fetch(url, {\n ...options,\n headers: {\n ...options.headers,\n Authorization: `Bearer ${token}`,\n },\n });\n },\n\n /**\n * Makes a fetch request with caching in localStorage.\n * @param url - The URL to fetch.\n * @param options - Fetch options.\n * @param cacheTime - Cache time in milliseconds (default 5 minutes).\n * @returns The fetch response (from cache or network).\n * @example\n * ```typescript\n * const res = await NetworkUtils.fetchWithCache('/api/data');\n * ```\n */\n fetchWithCache: async (\n url: string,\n options: RequestInit = {},\n cacheTime = 5 * 60 * 1000 // 5 minutes\n ): Promise<Response> => {\n const cacheKey = `fetch-cache-${url}`;\n const cached = localStorage.getItem(cacheKey);\n\n if (cached) {\n const { data, timestamp } = JSON.parse(cached);\n if (Date.now() - timestamp < cacheTime) {\n return new Response(data);\n }\n }\n\n const response = await fetch(url, options);\n const data = await response.clone().text();\n\n localStorage.setItem(\n cacheKey,\n JSON.stringify({\n data,\n timestamp: Date.now(),\n })\n );\n\n return response;\n },\n\n /**\n * Makes a fetch request and parses the response as JSON, with error handling.\n * @template T\n * @param url - The URL to fetch.\n * @param options - Fetch options.\n * @returns The parsed response data.\n * @throws {Error} If the response is not OK.\n * @example\n * ```typescript\n * const data = await NetworkUtils.fetchJson<{foo: string}>('/api/data');\n * ```\n */\n fetchJson: async <T>(url: string, options: RequestInit = {}): Promise<T> => {\n const response = await fetch(url, {\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n throw new Error(`HTTP error! status: ${response.status}`);\n }\n\n return response.json();\n },\n\n /**\n * Makes a fetch request and tracks download progress.\n * @param url - The URL to fetch.\n * @param options - Fetch options.\n * @param onProgress - Progress callback (0-100).\n * @returns The fetch response.\n * @example\n * ```typescript\n * await NetworkUtils.fetchWithProgress('/file', {}, (progress) => console.log('Progress:', progress));\n * ```\n */\n fetchWithProgress: async (\n url: string,\n options: RequestInit = {},\n onProgress?: (progress: number) => void\n ): Promise<Response> => {\n const response = await fetch(url, options);\n const contentLength = response.headers.get(\"content-length\");\n const total = contentLength ? parseInt(contentLength, 10) : 0;\n let loaded = 0;\n\n const reader = response.body?.getReader();\n if (!reader || !response.body) return response;\n\n const stream = new ReadableStream({\n start(controller) {\n function push() {\n reader!.read().then(({ done, value }) => {\n if (done) {\n controller.close();\n return;\n }\n\n loaded += value.length;\n if (total && onProgress) {\n onProgress((loaded / total) * 100);\n }\n\n controller.enqueue(value);\n push();\n });\n }\n\n push();\n },\n });\n\n return new Response(stream, {\n headers: response.headers,\n status: response.status,\n statusText: response.statusText,\n });\n },\n\n /**\n * Makes a fetch request with retry logic on failure.\n * @param url - The URL to fetch.\n * @param options - Fetch options.\n * @param retries - Number of retries (default 3).\n * @param delay - Delay between retries in milliseconds (default 1000).\n * @returns The fetch response.\n * @throws {Error} If all retries fail.\n * @example\n * ```typescript\n * const res = await NetworkUtils.fetchWithRetry('/api', {}, 5, 500);\n * ```\n */\n fetchWithRetry: async (\n url: string,\n options: RequestInit = {},\n retries = 3,\n delay = 1000\n ): Promise<Response> => {\n let lastError: Error;\n\n for (let i = 0; i < retries; i++) {\n try {\n return await fetch(url, options);\n } catch (error) {\n lastError = error as Error;\n if (i < retries - 1) {\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n\n throw lastError!;\n },\n\n /**\n * Makes a fetch request with a timeout.\n * @param url - The URL to fetch.\n * @param options - Fetch options.\n * @param timeout - Request timeout in milliseconds (default 5000).\n * @returns The fetch response.\n * @throws {Error} If the request times out.\n * @example\n * ```typescript\n * const res = await NetworkUtils.fetchWithTimeout('/api', {}, 2000);\n * ```\n */\n fetchWithTimeout: async (\n url: string,\n options: RequestInit = {},\n timeout = 5000\n ): Promise<Response> => {\n const controller = new AbortController();\n const { signal } = controller;\n\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await fetch(url, { ...options, signal });\n clearTimeout(timeoutId);\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new Error(\"Request timeout\");\n }\n throw error;\n }\n },\n\n /**\n * Gets the current network speed (downlink) in Mbps, if available.\n * @returns The network speed in Mbps, or null if not available.\n * @example\n * ```typescript\n * const speed = NetworkUtils.getNetworkSpeed();\n * console.log('Speed:', speed);\n * ```\n */\n getNetworkSpeed: (): string | null => {\n if (typeof navigator !== \"undefined\" && \"connection\" in navigator) {\n const connection = (navigator as any).connection;\n return connection ? connection.downlink + \" Mbps\" : null;\n }\n return null;\n },\n\n /**\n * Gets the current network type (e.g., 'wifi', '4g'), if available.\n * @returns The network type, or null if not available.\n * @example\n * ```typescript\n * const type = NetworkUtils.getNetworkType();\n * console.log('Type:', type);\n * ```\n */\n getNetworkType: (): string | null => {\n if (typeof navigator !== \"undefined\" && \"connection\" in navigator) {\n const connection = (navigator as any).connection;\n return connection ? connection.effectiveType : null;\n }\n return null;\n },\n\n /**\n * Checks if the network is currently online.\n * @returns True if the network is online, false otherwise.\n * @example\n * ```typescript\n * if (NetworkUtils.isOnline()) {\n * // Do something when online\n * }\n * ```\n */\n isOnline: (): boolean => {\n return typeof navigator !== \"undefined\" && navigator.onLine;\n },\n};\n"],"names":["data"],"mappings":"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"}