Main coves client
1import 'identity_resolver_error.dart';
2
3/// Normalizes a handle to lowercase.
4String normalizeHandle(String handle) => handle.toLowerCase();
5
6/// Checks if a handle is valid according to atProto spec.
7///
8/// A valid handle must:
9/// - Be between 1 and 253 characters
10/// - Match the pattern: subdomain.domain.tld
11/// - Each label must start and end with alphanumeric
12/// - Labels can contain hyphens but not at boundaries
13bool isValidHandle(String handle) {
14 if (handle.isEmpty || handle.length >= 254) return false;
15
16 // Pattern: ([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])?
17 final pattern = RegExp(
18 r'^([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])?$',
19 );
20
21 return pattern.hasMatch(handle);
22}
23
24/// Returns a normalized handle if valid, null otherwise.
25String? asNormalizedHandle(String input) {
26 final handle = normalizeHandle(input);
27 return isValidHandle(handle) ? handle : null;
28}
29
30/// Asserts that a handle is valid.
31void assertValidHandle(String handle) {
32 if (!isValidHandle(handle)) {
33 throw InvalidHandleError(handle, 'Invalid handle format');
34 }
35}