Suite of AT Protocol TypeScript libraries built on web standards
21
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 159 lines 4.0 kB view raw
1import { 2 ensureValidAtUri, 3 ensureValidDid, 4 ensureValidHandle, 5 ensureValidNsid, 6 ensureValidRecordKey, 7 ensureValidTid, 8} from "@atp/syntax"; 9import { ensureValidCidString } from "../data/cid.ts"; 10import { isLanguage } from "../data/strings.ts"; 11 12declare const __brand: unique symbol; 13type Brand<T, B> = T & { [__brand]: B }; 14 15export type DidString = Brand<string, "did">; 16export type HandleString = Brand<string, "handle">; 17export type AtUriString = Brand<string, "at-uri">; 18export type AtIdentifierString = Brand<string, "at-identifier">; 19export type NsidString = `${string}.${string}.${string}`; 20export type CidString = Brand<string, "cid">; 21export type TidString = Brand<string, "tid">; 22export type RecordKeyString = Brand<string, "record-key">; 23export type DatetimeString = Brand<string, "datetime">; 24export type UriString = `${string}:${string}`; 25export type LanguageString = string; 26 27export const STRING_FORMATS: readonly [ 28 "datetime", 29 "uri", 30 "at-uri", 31 "did", 32 "handle", 33 "at-identifier", 34 "nsid", 35 "cid", 36 "language", 37 "tid", 38 "record-key", 39] = Object.freeze( 40 [ 41 "datetime", 42 "uri", 43 "at-uri", 44 "did", 45 "handle", 46 "at-identifier", 47 "nsid", 48 "cid", 49 "language", 50 "tid", 51 "record-key", 52 ] as const, 53); 54 55export type StringFormat = (typeof STRING_FORMATS)[number]; 56 57export type InferStringFormat<F> = F extends "datetime" ? DatetimeString 58 : F extends "uri" ? UriString 59 : F extends "at-uri" ? AtUriString 60 : F extends "did" ? DidString 61 : F extends "handle" ? HandleString 62 : F extends "at-identifier" ? AtIdentifierString 63 : F extends "nsid" ? NsidString 64 : F extends "cid" ? CidString 65 : F extends "language" ? LanguageString 66 : F extends "tid" ? TidString 67 : F extends "record-key" ? RecordKeyString 68 : string; 69 70export function assertDid(input: string): asserts input is DidString { 71 ensureValidDid(input); 72} 73 74export function assertHandle(input: string): asserts input is HandleString { 75 ensureValidHandle(input); 76} 77 78export function assertAtUri(input: string): asserts input is AtUriString { 79 ensureValidAtUri(input); 80} 81 82export function assertAtIdentifier( 83 input: string, 84): asserts input is AtIdentifierString { 85 try { 86 ensureValidDid(input); 87 return; 88 } catch { 89 // did format failed 90 } 91 ensureValidHandle(input); 92} 93 94export function assertNsid(input: string): asserts input is NsidString { 95 ensureValidNsid(input); 96} 97 98export function assertTid(input: string): asserts input is TidString { 99 ensureValidTid(input); 100} 101 102export function assertRecordKey( 103 input: string, 104): asserts input is RecordKeyString { 105 ensureValidRecordKey(input); 106} 107 108export function assertDatetime(input: string): asserts input is DatetimeString { 109 if ( 110 !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/.test( 111 input, 112 ) 113 ) { 114 throw new Error(`Invalid datetime: ${input}`); 115 } 116} 117 118export function assertCidString(input: string): asserts input is CidString { 119 ensureValidCidString(input); 120} 121 122export function assertUri(input: string): asserts input is UriString { 123 if (!/^\w+:(?:\/\/)?[^\s/][^\s]*$/.test(input)) { 124 throw new Error("Invalid URI"); 125 } 126} 127 128export function assertLanguage( 129 input: string, 130): asserts input is LanguageString { 131 if (!isLanguage(input)) { 132 throw new Error("Invalid BCP 47 string"); 133 } 134} 135 136const formatters = new Map<StringFormat, (str: string) => void>( 137 [ 138 ["datetime", assertDatetime], 139 ["uri", assertUri], 140 ["at-uri", assertAtUri], 141 ["did", assertDid], 142 ["handle", assertHandle], 143 ["at-identifier", assertAtIdentifier], 144 ["nsid", assertNsid], 145 ["cid", assertCidString], 146 ["language", assertLanguage], 147 ["tid", assertTid], 148 ["record-key", assertRecordKey], 149 ] as const, 150); 151 152export function assertStringFormat<F extends StringFormat>( 153 input: string, 154 format: F, 155): asserts input is InferStringFormat<F> { 156 const assertFn = formatters.get(format); 157 if (assertFn) assertFn(input); 158 else throw new Error(`Unknown string format: ${format}`); 159}