UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

1 lines 26.2 kB
{"version":3,"file":"url.cjs","sources":["../../../src/utils/url.ts"],"sourcesContent":["import type {XID} from '../types';\n\n// URL parsing and manipulation utilities\nexport interface ParsedURL {\n protocol: string;\n hostname: string;\n port?: string;\n pathname: string;\n search: string;\n hash: string;\n query: Record<string, string | string[]>;\n origin: string;\n href: string;\n}\n\nexport const parseURL = (url: string): ParsedURL | null => {\n try {\n const urlObj = new URL(url);\n const query = parseQueryString(urlObj.search);\n\n return {\n protocol: urlObj.protocol,\n hostname: urlObj.hostname,\n port: urlObj.port || undefined,\n pathname: urlObj.pathname,\n search: urlObj.search,\n hash: urlObj.hash,\n query,\n origin: urlObj.origin,\n href: urlObj.href,\n };\n } catch {\n return null;\n }\n};\n\nexport const buildURL = (\n base: string,\n params?: Record<string, string | number | boolean | undefined | null>\n): string => {\n try {\n const url = new URL(base);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n return url.toString();\n } catch {\n return base;\n }\n};\n\nexport const addQueryParams = (\n url: string,\n params: Record<string, string | number | boolean | undefined | null>\n): string => {\n return buildURL(url, params);\n};\n\nexport const parseQueryString = (queryString: string): Record<string, string | string[]> => {\n const params = new URLSearchParams(queryString);\n const result: Record<string, string | string[]> = {};\n\n for (const [key, value] of params.entries()) {\n if (key in result) {\n if (Array.isArray(result[key])) {\n (result[key] as string[]).push(value);\n } else {\n result[key] = [result[key] as string, value];\n }\n } else {\n result[key] = value;\n }\n }\n\n return result;\n};\n\nexport const buildQueryString = (params: Record<string, any>): string => {\n const searchParams = new URLSearchParams();\n\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n for (const item of value) {\n searchParams.append(key, String(item));\n }\n } else {\n searchParams.set(key, String(value));\n }\n }\n }\n\n return searchParams.toString();\n};\n\nexport const removeQueryParams = (url: string, keys: string[]): string => {\n try {\n const urlObj = new URL(url);\n\n for (const key of keys) {\n urlObj.searchParams.delete(key);\n }\n\n return urlObj.toString();\n } catch {\n return url;\n }\n};\n\nexport const getQueryParam = (url: string, key: string): string | null => {\n try {\n const urlObj = new URL(url);\n return urlObj.searchParams.get(key);\n } catch {\n return null;\n }\n};\n\nexport const hasQueryParam = (url: string, key: string): boolean => {\n try {\n const urlObj = new URL(url);\n return urlObj.searchParams.has(key);\n } catch {\n return false;\n }\n};\n\n// Auth-specific URL utilities\nexport const buildAuthURL = (\n baseUrl: string,\n type: 'signin' | 'signup' | 'reset' | 'verify',\n params?: {\n organizationId?: XID;\n redirectUrl?: string;\n invitationToken?: string;\n emailAddress?: string;\n mode?: string;\n [key: string]: any;\n }\n): string => {\n const paths = {\n signin: '/sign-in',\n signup: '/sign-up',\n reset: '/reset-password',\n verify: '/verify',\n };\n\n const url = new URL(paths[type], baseUrl);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n return url.toString();\n};\n\nexport const buildOAuthURL = (\n provider: string,\n clientId: string,\n redirectUri: string,\n options?: {\n state?: string;\n scope?: string | string[];\n responseType?: string;\n codeChallenge?: string;\n codeChallengeMethod?: string;\n organizationId?: XID;\n [key: string]: any;\n }\n): string => {\n const baseUrls: Record<string, string> = {\n google: 'https://accounts.google.com/o/oauth2/v2/auth',\n github: 'https://github.com/login/oauth/authorize',\n microsoft: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',\n facebook: 'https://www.facebook.com/v18.0/dialog/oauth',\n apple: 'https://appleid.apple.com/auth/authorize',\n twitter: 'https://twitter.com/i/oauth2/authorize',\n linkedin: 'https://www.linkedin.com/oauth/v2/authorization',\n discord: 'https://discord.com/api/oauth2/authorize',\n slack: 'https://slack.com/oauth/v2/authorize',\n spotify: 'https://accounts.spotify.com/authorize',\n };\n\n const baseUrl = baseUrls[provider.toLowerCase()];\n if (!baseUrl) {\n throw new Error(`Unsupported OAuth provider: ${provider}`);\n }\n\n const params: Record<string, string> = {\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: options?.responseType || 'code',\n };\n\n if (options?.state) {\n params.state = options.state;\n }\n\n if (options?.scope) {\n params.scope = Array.isArray(options.scope)\n ? options.scope.join(' ')\n : options.scope;\n }\n\n if (options?.codeChallenge && options?.codeChallengeMethod) {\n params.code_challenge = options.codeChallenge;\n params.code_challenge_method = options.codeChallengeMethod;\n }\n\n // Add provider-specific parameters\n if (options?.organizationId) {\n params.organization_id = options.organizationId;\n }\n\n // Add any additional parameters\n if (options) {\n for (const [key, value] of Object.entries(options)) {\n if (value !== undefined && value !== null &&\n !['state', 'scope', 'responseType', 'codeChallenge', 'codeChallengeMethod', 'organizationId'].includes(key)) {\n params[key] = String(value);\n }\n }\n }\n\n return buildURL(baseUrl, params);\n};\n\nexport const parseOAuthCallback = (url: string): {\n code?: string;\n state?: string;\n error?: string;\n errorDescription?: string;\n organizationId?: XID;\n} => {\n const parsed = parseURL(url);\n if (!parsed) return {};\n\n return {\n code: typeof parsed.query.code === 'string' ? parsed.query.code : undefined,\n state: typeof parsed.query.state === 'string' ? parsed.query.state : undefined,\n error: typeof parsed.query.error === 'string' ? parsed.query.error : undefined,\n errorDescription: typeof parsed.query.error_description === 'string'\n ? parsed.query.error_description\n : undefined,\n organizationId: typeof parsed.query.organization_id === 'string'\n ? parsed.query.organization_id as XID\n : undefined,\n };\n};\n\nexport const buildMagicLinkURL = (\n baseUrl: string,\n token: string,\n options?: {\n redirectUrl?: string;\n organizationId?: XID;\n mode?: string;\n }\n): string => {\n const url = new URL('/auth/magic-link', baseUrl);\n url.searchParams.set('token', token);\n\n if (options?.redirectUrl) {\n url.searchParams.set('redirect_url', options.redirectUrl);\n }\n\n if (options?.organizationId) {\n url.searchParams.set('organization_id', options.organizationId);\n }\n\n if (options?.mode) {\n url.searchParams.set('mode', options.mode);\n }\n\n return url.toString();\n};\n\nexport const buildVerificationURL = (\n baseUrl: string,\n token: string,\n type: 'email' | 'phone',\n options?: {\n redirectUrl?: string;\n organizationId?: XID;\n }\n): string => {\n const url = new URL(`/auth/verify-${type}`, baseUrl);\n url.searchParams.set('token', token);\n\n if (options?.redirectUrl) {\n url.searchParams.set('redirect_url', options.redirectUrl);\n }\n\n if (options?.organizationId) {\n url.searchParams.set('organization_id', options.organizationId);\n }\n\n return url.toString();\n};\n\nexport const buildPasswordResetURL = (\n baseUrl: string,\n token: string,\n options?: {\n redirectUrl?: string;\n organizationId?: XID;\n }\n): string => {\n const url = new URL('/auth/reset-password', baseUrl);\n url.searchParams.set('token', token);\n\n if (options?.redirectUrl) {\n url.searchParams.set('redirect_url', options.redirectUrl);\n }\n\n if (options?.organizationId) {\n url.searchParams.set('organization_id', options.organizationId);\n }\n\n return url.toString();\n};\n\nexport const buildInvitationURL = (\n baseUrl: string,\n token: string,\n options?: {\n redirectUrl?: string;\n organizationId?: XID;\n }\n): string => {\n const url = new URL('/auth/invitation', baseUrl);\n url.searchParams.set('token', token);\n\n if (options?.redirectUrl) {\n url.searchParams.set('redirect_url', options.redirectUrl);\n }\n\n if (options?.organizationId) {\n url.searchParams.set('organization_id', options.organizationId);\n }\n\n return url.toString();\n};\n\n// URL validation utilities\nexport const isValidURL = (url: string): boolean => {\n try {\n new URL(url);\n return true;\n } catch {\n return false;\n }\n};\n\nexport const isValidHttpURL = (url: string): boolean => {\n try {\n const urlObj = new URL(url);\n return urlObj.protocol === 'http:' || urlObj.protocol === 'https:';\n } catch {\n return false;\n }\n};\n\nexport const isValidHttpsURL = (url: string): boolean => {\n try {\n const urlObj = new URL(url);\n return urlObj.protocol === 'https:';\n } catch {\n return false;\n }\n};\n\nexport const isDomainAllowed = (url: string, allowedDomains: string[]): boolean => {\n try {\n const urlObj = new URL(url);\n const hostname = urlObj.hostname.toLowerCase();\n\n return allowedDomains.some(domain => {\n const normalizedDomain = domain.toLowerCase();\n return hostname === normalizedDomain ||\n hostname.endsWith(`.${normalizedDomain}`);\n });\n } catch {\n return false;\n }\n};\n\nexport const isSubdomain = (url: string, parentDomain: string): boolean => {\n try {\n const urlObj = new URL(url);\n const hostname = urlObj.hostname.toLowerCase();\n const parent = parentDomain.toLowerCase();\n\n return hostname === parent || hostname.endsWith(`.${parent}`);\n } catch {\n return false;\n }\n};\n\n// URL manipulation utilities\nexport const extractDomain = (url: string): string | null => {\n try {\n const urlObj = new URL(url);\n return urlObj.hostname;\n } catch {\n return null;\n }\n};\n\nexport const extractRootDomain = (url: string): string | null => {\n const domain = extractDomain(url);\n if (!domain) return null;\n\n const parts = domain.split('.');\n if (parts.length >= 2) {\n return parts.slice(-2).join('.');\n }\n\n return domain;\n};\n\nexport const normalizeURL = (url: string): string => {\n try {\n const urlObj = new URL(url);\n\n // Remove default ports\n if ((urlObj.protocol === 'http:' && urlObj.port === '80') ||\n (urlObj.protocol === 'https:' && urlObj.port === '443')) {\n urlObj.port = '';\n }\n\n // Remove trailing slash from pathname\n if (urlObj.pathname !== '/' && urlObj.pathname.endsWith('/')) {\n urlObj.pathname = urlObj.pathname.slice(0, -1);\n }\n\n // Sort query parameters\n const params = Array.from(urlObj.searchParams.entries())\n .sort(([a], [b]) => a.localeCompare(b));\n\n urlObj.search = '';\n for (const [key, value] of params) {\n urlObj.searchParams.append(key, value);\n }\n\n return urlObj.toString();\n } catch {\n return url;\n }\n};\n\nexport const joinURL = (...parts: string[]): string => {\n if (parts.length === 0) return '';\n\n const [base, ...rest] = parts;\n let result = base.replace(/\\/+$/, '');\n\n for (const part of rest) {\n const cleanPart = part.replace(/^\\/+|\\/+$/g, '');\n if (cleanPart) {\n result += '/' + cleanPart;\n }\n }\n\n return result;\n};\n\nexport const getURLPath = (url: string): string => {\n try {\n const urlObj = new URL(url);\n return urlObj.pathname;\n } catch {\n return '';\n }\n};\n\nexport const getURLParams = (url: string): Record<string, string | string[]> => {\n try {\n const urlObj = new URL(url);\n return parseQueryString(urlObj.search);\n } catch {\n return {};\n }\n};\n\n// Redirect utilities\nexport const isSafeRedirectURL = (\n url: string,\n allowedDomains: string[],\n allowRelative = true\n): boolean => {\n if (!url) return false;\n\n // Allow relative URLs if enabled\n if (allowRelative && url.startsWith('/')) {\n return true;\n }\n\n // Check if it's a valid absolute URL\n if (!isValidHttpURL(url)) {\n return false;\n }\n\n // Check if domain is allowed\n return isDomainAllowed(url, allowedDomains);\n};\n\nexport const sanitizeRedirectURL = (\n url: string,\n allowedDomains: string[],\n fallbackURL = '/'\n): string => {\n if (isSafeRedirectURL(url, allowedDomains)) {\n return url;\n }\n\n return fallbackURL;\n};\n\n// Browser utilities\nexport const getCurrentURL = (): string => {\n return typeof window !== 'undefined' ? window.location.href : '';\n};\n\nexport const getCurrentPath = (): string => {\n return typeof window !== 'undefined' ? window.location.pathname : '';\n};\n\nexport const getCurrentDomain = (): string => {\n return typeof window !== 'undefined' ? window.location.hostname : '';\n};\n\nexport const getCurrentOrigin = (): string => {\n return typeof window !== 'undefined' ? window.location.origin : '';\n};\n\nexport const getCurrentParams = (): Record<string, string | string[]> => {\n return typeof window !== 'undefined'\n ? parseQueryString(window.location.search)\n : {};\n};\n\nexport const redirectTo = (url: string, replace = false): void => {\n if (typeof window !== 'undefined') {\n if (replace) {\n window.location.replace(url);\n } else {\n window.location.href = url;\n }\n }\n};\n\nexport const openInNewTab = (url: string): void => {\n if (typeof window !== 'undefined') {\n window.open(url, '_blank', 'noopener,noreferrer');\n }\n};\n\n// Hash utilities\nexport const getHash = (): string => {\n return typeof window !== 'undefined' ? window.location.hash : '';\n};\n\nexport const setHash = (hash: string): void => {\n if (typeof window !== 'undefined') {\n window.location.hash = hash;\n }\n};\n\nexport const removeHash = (): void => {\n if (typeof window !== 'undefined') {\n window.history.replaceState('', document.title, window.location.pathname + window.location.search);\n }\n};\n\n// URL encoding utilities\nexport const encodeURIComponentSafe = (str: string): string => {\n return encodeURIComponent(str)\n .replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);\n};\n\nexport const decodeURIComponentSafe = (str: string): string => {\n try {\n return decodeURIComponent(str);\n } catch {\n return str;\n }\n};\n\n// Export utilities object\nexport const URLUtils = {\n // Parsing\n parseURL,\n parseQueryString,\n parseOAuthCallback,\n\n // Building\n buildURL,\n buildQueryString,\n buildAuthURL,\n buildOAuthURL,\n buildMagicLinkURL,\n buildVerificationURL,\n buildPasswordResetURL,\n buildInvitationURL,\n\n // Manipulation\n addQueryParams,\n removeQueryParams,\n getQueryParam,\n hasQueryParam,\n joinURL,\n normalizeURL,\n\n // Validation\n isValidURL,\n isValidHttpURL,\n isValidHttpsURL,\n isDomainAllowed,\n isSubdomain,\n isSafeRedirectURL,\n\n // Extraction\n extractDomain,\n extractRootDomain,\n getURLPath,\n getURLParams,\n\n // Browser\n getCurrentURL,\n getCurrentPath,\n getCurrentDomain,\n getCurrentOrigin,\n getCurrentParams,\n redirectTo,\n openInNewTab,\n\n // Hash\n getHash,\n setHash,\n removeHash,\n\n // Encoding\n encodeURIComponentSafe,\n decodeURIComponentSafe,\n\n // Security\n sanitizeRedirectURL,\n};"],"names":["parseURL","url","urlObj","query","parseQueryString","buildURL","base","params","key","value","addQueryParams","queryString","result","buildQueryString","searchParams","item","removeQueryParams","keys","getQueryParam","hasQueryParam","buildAuthURL","baseUrl","type","paths","buildOAuthURL","provider","clientId","redirectUri","options","parseOAuthCallback","parsed","buildMagicLinkURL","token","buildVerificationURL","buildPasswordResetURL","buildInvitationURL","isValidURL","isValidHttpURL","isValidHttpsURL","isDomainAllowed","allowedDomains","hostname","domain","normalizedDomain","isSubdomain","parentDomain","parent","extractDomain","extractRootDomain","parts","normalizeURL","a","b","joinURL","rest","part","cleanPart","getURLPath","getURLParams","isSafeRedirectURL","allowRelative","sanitizeRedirectURL","fallbackURL","getCurrentURL","getCurrentPath","getCurrentDomain","getCurrentOrigin","getCurrentParams","redirectTo","replace","openInNewTab","getHash","setHash","hash","removeHash","encodeURIComponentSafe","str","c","decodeURIComponentSafe","URLUtils"],"mappings":"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"}