mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1// Regex from the go implementation
2// https://github.com/bluesky-social/indigo/blob/main/atproto/syntax/handle.go#L10
3import {forceLTR} from '#/lib/strings/bidi'
4
5const VALIDATE_REGEX =
6 /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/
7
8export const MAX_SERVICE_HANDLE_LENGTH = 18
9
10export function makeValidHandle(str: string): string {
11 if (str.length > 20) {
12 str = str.slice(0, 20)
13 }
14 str = str.toLowerCase()
15 return str.replace(/^[^a-z0-9]+/g, '').replace(/[^a-z0-9-]/g, '')
16}
17
18export function createFullHandle(name: string, domain: string): string {
19 name = (name || '').replace(/[.]+$/, '')
20 domain = (domain || '').replace(/^[.]+/, '')
21 return `${name}.${domain}`
22}
23
24export function isInvalidHandle(handle: string): boolean {
25 return handle === 'handle.invalid'
26}
27
28export function sanitizeHandle(
29 handle: string,
30 prefix = '',
31 forceLeftToRight = true,
32): string {
33 const lowercasedWithPrefix = `${prefix}${handle.toLocaleLowerCase()}`
34 return isInvalidHandle(handle)
35 ? '⚠Invalid Handle'
36 : forceLeftToRight
37 ? forceLTR(lowercasedWithPrefix)
38 : lowercasedWithPrefix
39}
40
41export interface IsValidHandle {
42 handleChars: boolean
43 hyphenStartOrEnd: boolean
44 frontLengthNotTooShort: boolean
45 frontLengthNotTooLong: boolean
46 totalLength: boolean
47 overall: boolean
48}
49
50// More checks from https://github.com/bluesky-social/atproto/blob/main/packages/pds/src/handle/index.ts#L72
51export function validateServiceHandle(
52 str: string,
53 userDomain: string,
54): IsValidHandle {
55 const fullHandle = createFullHandle(str, userDomain)
56
57 const results = {
58 handleChars:
59 !str || (VALIDATE_REGEX.test(fullHandle) && !str.includes('.')),
60 hyphenStartOrEnd: !str.startsWith('-') && !str.endsWith('-'),
61 frontLengthNotTooShort: str.length >= 3,
62 frontLengthNotTooLong: str.length <= MAX_SERVICE_HANDLE_LENGTH,
63 totalLength: fullHandle.length <= 253,
64 }
65
66 return {
67 ...results,
68 overall: !Object.values(results).includes(false),
69 }
70}