Auth.constants.ts46 lines · main
| 1 | // Regex from: https://stackoverflow.com/a/68002755/4807782 |
| 2 | // modified to accept numbers in the body of domain though |
| 3 | // examples of matches: |
| 4 | // "vercel.com" |
| 5 | // "www.vercel.com" |
| 6 | // "uptime-monitor-fe.vercel.app" |
| 7 | // "https://uptime-monitor-fe.vercel.app/" |
| 8 | |
| 9 | // Supports wildcards, port numbers at the end, paths at the end and query params |
| 10 | const baseUrlRegex = |
| 11 | /^((ftp|http|https):\/\/)?(www.)?(?!.*(ftp|http|https|www.))[a-zA-Z0-9_*-]+(\.[a-zA-Z0-9_*-]+)+((\/)[\w#]+)*(\/\w+\?[a-zA-Z0-9_]+=\w+(&[a-zA-Z0-9_]+=\w+)*)+(?:\.[a-z]+)*(?::\d+)?(?![^<]*(?:<\/\w+>|\/?>))(.*)?\/?(.)*?$/gm |
| 12 | |
| 13 | // iOS deep linking scheme https://benoitpasquier.com/deep-linking-url-scheme-ios/ |
| 14 | const appRegex = |
| 15 | /^[a-z0-9-]+([.][a-z0-9]+)*:\/(\/[-a-z0-9._~!$&'()*+,;=:@%]+)+(?:\.[a-z]+)*(?::\d+)?(?![^<]*(?:<\/\w+>|\/?>))(.*)?\/?(.)*?$/i |
| 16 | |
| 17 | // Regex from https://stackoverflow.com/a/18696953/4807782 |
| 18 | const localhostRegex = /^(?:^|\s)((https?:\/\/)?(?:localhost|[\w-]+(?:\.[\w-]+)+)(:\d+)?(\/\S*)?)/i |
| 19 | |
| 20 | // "chrome-extension://<extension-id>" |
| 21 | const chromeExtensionRegex = /chrome-extension:\/\/([a-zA-Z]*)/gm |
| 22 | |
| 23 | // New regex for custom scheme URLs |
| 24 | const customSchemeRegex = /^([a-zA-Z][a-zA-Z0-9+.-]*):(?:\/{1,3})?([a-zA-Z0-9_.-]*)$/ |
| 25 | |
| 26 | // Exclude simple domain names without protocol |
| 27 | const excludeSimpleDomainRegex = /^[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$/ |
| 28 | |
| 29 | // combine the above regexes, with optional exclusion of options |
| 30 | // usage: urlRegex() or urlRegex({ excludeSimpleDomains: false }) |
| 31 | export function urlRegex( |
| 32 | options: { excludeSimpleDomains?: boolean } = { excludeSimpleDomains: true } |
| 33 | ): RegExp { |
| 34 | const { excludeSimpleDomains } = options |
| 35 | const excludeSimpleDomainPart = excludeSimpleDomains |
| 36 | ? `(?!${excludeSimpleDomainRegex.source})` |
| 37 | : '' |
| 38 | |
| 39 | return new RegExp( |
| 40 | `${excludeSimpleDomainPart}((${baseUrlRegex.source})|(${localhostRegex.source})|(${appRegex.source})|(${chromeExtensionRegex.source})|(${customSchemeRegex.source}))`, |
| 41 | 'i' |
| 42 | ) |
| 43 | } |
| 44 | |
| 45 | // Use a const string to represent no chars option. Represented as empty string on the backend side. |
| 46 | export const NO_REQUIRED_CHARACTERS = 'NO_REQUIRED_CHARS' |