this repo has no description
1const API_BASE = '/xrpc' 2 3export class ApiError extends Error { 4 public did?: string 5 6 constructor(public status: number, public error: string, message: string, did?: string) { 7 super(message) 8 this.name = 'ApiError' 9 this.did = did 10 } 11} 12 13async function xrpc<T>(method: string, options?: { 14 method?: 'GET' | 'POST' 15 params?: Record<string, string> 16 body?: unknown 17 token?: string 18}): Promise<T> { 19 const { method: httpMethod = 'GET', params, body, token } = options ?? {} 20 21 let url = `${API_BASE}/${method}` 22 if (params) { 23 const searchParams = new URLSearchParams(params) 24 url += `?${searchParams}` 25 } 26 27 const headers: Record<string, string> = {} 28 if (token) { 29 headers['Authorization'] = `Bearer ${token}` 30 } 31 if (body) { 32 headers['Content-Type'] = 'application/json' 33 } 34 35 const res = await fetch(url, { 36 method: httpMethod, 37 headers, 38 body: body ? JSON.stringify(body) : undefined, 39 }) 40 41 if (!res.ok) { 42 const err = await res.json().catch(() => ({ error: 'Unknown', message: res.statusText })) 43 throw new ApiError(res.status, err.error, err.message, err.did) 44 } 45 46 return res.json() 47} 48 49export interface Session { 50 did: string 51 handle: string 52 email?: string 53 emailConfirmed?: boolean 54 preferredChannel?: string 55 preferredChannelVerified?: boolean 56 accessJwt: string 57 refreshJwt: string 58} 59 60export interface AppPassword { 61 name: string 62 createdAt: string 63} 64 65export interface InviteCode { 66 code: string 67 available: number 68 disabled: boolean 69 forAccount: string 70 createdBy: string 71 createdAt: string 72 uses: { usedBy: string; usedAt: string }[] 73} 74 75export type VerificationChannel = 'email' | 'discord' | 'telegram' | 'signal' 76 77export interface CreateAccountParams { 78 handle: string 79 email: string 80 password: string 81 inviteCode?: string 82 verificationChannel?: VerificationChannel 83 discordId?: string 84 telegramUsername?: string 85 signalNumber?: string 86} 87 88export interface CreateAccountResult { 89 handle: string 90 did: string 91 verificationRequired: boolean 92 verificationChannel: string 93} 94 95export interface ConfirmSignupResult { 96 accessJwt: string 97 refreshJwt: string 98 handle: string 99 did: string 100 email?: string 101 emailConfirmed?: boolean 102 preferredChannel?: string 103 preferredChannelVerified?: boolean 104} 105 106export const api = { 107 async createAccount(params: CreateAccountParams): Promise<CreateAccountResult> { 108 return xrpc('com.atproto.server.createAccount', { 109 method: 'POST', 110 body: { 111 handle: params.handle, 112 email: params.email, 113 password: params.password, 114 inviteCode: params.inviteCode, 115 verificationChannel: params.verificationChannel, 116 discordId: params.discordId, 117 telegramUsername: params.telegramUsername, 118 signalNumber: params.signalNumber, 119 }, 120 }) 121 }, 122 123 async confirmSignup(did: string, verificationCode: string): Promise<ConfirmSignupResult> { 124 return xrpc('com.atproto.server.confirmSignup', { 125 method: 'POST', 126 body: { did, verificationCode }, 127 }) 128 }, 129 130 async resendVerification(did: string): Promise<{ success: boolean }> { 131 return xrpc('com.atproto.server.resendVerification', { 132 method: 'POST', 133 body: { did }, 134 }) 135 }, 136 137 async createSession(identifier: string, password: string): Promise<Session> { 138 return xrpc('com.atproto.server.createSession', { 139 method: 'POST', 140 body: { identifier, password }, 141 }) 142 }, 143 144 async getSession(token: string): Promise<Session> { 145 return xrpc('com.atproto.server.getSession', { token }) 146 }, 147 148 async refreshSession(refreshJwt: string): Promise<Session> { 149 return xrpc('com.atproto.server.refreshSession', { 150 method: 'POST', 151 token: refreshJwt, 152 }) 153 }, 154 155 async deleteSession(token: string): Promise<void> { 156 await xrpc('com.atproto.server.deleteSession', { 157 method: 'POST', 158 token, 159 }) 160 }, 161 162 async listAppPasswords(token: string): Promise<{ passwords: AppPassword[] }> { 163 return xrpc('com.atproto.server.listAppPasswords', { token }) 164 }, 165 166 async createAppPassword(token: string, name: string): Promise<{ name: string; password: string; createdAt: string }> { 167 return xrpc('com.atproto.server.createAppPassword', { 168 method: 'POST', 169 token, 170 body: { name }, 171 }) 172 }, 173 174 async revokeAppPassword(token: string, name: string): Promise<void> { 175 await xrpc('com.atproto.server.revokeAppPassword', { 176 method: 'POST', 177 token, 178 body: { name }, 179 }) 180 }, 181 182 async getAccountInviteCodes(token: string): Promise<{ codes: InviteCode[] }> { 183 return xrpc('com.atproto.server.getAccountInviteCodes', { token }) 184 }, 185 186 async createInviteCode(token: string, useCount: number = 1): Promise<{ code: string }> { 187 return xrpc('com.atproto.server.createInviteCode', { 188 method: 'POST', 189 token, 190 body: { useCount }, 191 }) 192 }, 193 194 async requestPasswordReset(email: string): Promise<void> { 195 await xrpc('com.atproto.server.requestPasswordReset', { 196 method: 'POST', 197 body: { email }, 198 }) 199 }, 200 201 async resetPassword(token: string, password: string): Promise<void> { 202 await xrpc('com.atproto.server.resetPassword', { 203 method: 'POST', 204 body: { token, password }, 205 }) 206 }, 207 208 async requestEmailUpdate(token: string): Promise<{ tokenRequired: boolean }> { 209 return xrpc('com.atproto.server.requestEmailUpdate', { 210 method: 'POST', 211 token, 212 }) 213 }, 214 215 async updateEmail(token: string, email: string, emailToken?: string): Promise<void> { 216 await xrpc('com.atproto.server.updateEmail', { 217 method: 'POST', 218 token, 219 body: { email, token: emailToken }, 220 }) 221 }, 222 223 async updateHandle(token: string, handle: string): Promise<void> { 224 await xrpc('com.atproto.identity.updateHandle', { 225 method: 'POST', 226 token, 227 body: { handle }, 228 }) 229 }, 230 231 async requestAccountDelete(token: string): Promise<void> { 232 await xrpc('com.atproto.server.requestAccountDelete', { 233 method: 'POST', 234 token, 235 }) 236 }, 237 238 async deleteAccount(did: string, password: string, deleteToken: string): Promise<void> { 239 await xrpc('com.atproto.server.deleteAccount', { 240 method: 'POST', 241 body: { did, password, token: deleteToken }, 242 }) 243 }, 244 245 async describeServer(): Promise<{ 246 availableUserDomains: string[] 247 inviteCodeRequired: boolean 248 links?: { privacyPolicy?: string; termsOfService?: string } 249 }> { 250 return xrpc('com.atproto.server.describeServer') 251 }, 252 253 async getNotificationPrefs(token: string): Promise<{ 254 preferredChannel: string 255 email: string 256 discordId: string | null 257 discordVerified: boolean 258 telegramUsername: string | null 259 telegramVerified: boolean 260 signalNumber: string | null 261 signalVerified: boolean 262 }> { 263 return xrpc('com.bspds.account.getNotificationPrefs', { token }) 264 }, 265 266 async updateNotificationPrefs(token: string, prefs: { 267 preferredChannel?: string 268 discordId?: string 269 telegramUsername?: string 270 signalNumber?: string 271 }): Promise<{ success: boolean }> { 272 return xrpc('com.bspds.account.updateNotificationPrefs', { 273 method: 'POST', 274 token, 275 body: prefs, 276 }) 277 }, 278 279 async describeRepo(token: string, repo: string): Promise<{ 280 handle: string 281 did: string 282 didDoc: unknown 283 collections: string[] 284 handleIsCorrect: boolean 285 }> { 286 return xrpc('com.atproto.repo.describeRepo', { 287 token, 288 params: { repo }, 289 }) 290 }, 291 292 async listRecords(token: string, repo: string, collection: string, options?: { 293 limit?: number 294 cursor?: string 295 reverse?: boolean 296 }): Promise<{ 297 records: Array<{ uri: string; cid: string; value: unknown }> 298 cursor?: string 299 }> { 300 const params: Record<string, string> = { repo, collection } 301 if (options?.limit) params.limit = String(options.limit) 302 if (options?.cursor) params.cursor = options.cursor 303 if (options?.reverse) params.reverse = 'true' 304 return xrpc('com.atproto.repo.listRecords', { token, params }) 305 }, 306 307 async getRecord(token: string, repo: string, collection: string, rkey: string): Promise<{ 308 uri: string 309 cid: string 310 value: unknown 311 }> { 312 return xrpc('com.atproto.repo.getRecord', { 313 token, 314 params: { repo, collection, rkey }, 315 }) 316 }, 317 318 async createRecord(token: string, repo: string, collection: string, record: unknown, rkey?: string): Promise<{ 319 uri: string 320 cid: string 321 }> { 322 return xrpc('com.atproto.repo.createRecord', { 323 method: 'POST', 324 token, 325 body: { repo, collection, record, rkey }, 326 }) 327 }, 328 329 async putRecord(token: string, repo: string, collection: string, rkey: string, record: unknown): Promise<{ 330 uri: string 331 cid: string 332 }> { 333 return xrpc('com.atproto.repo.putRecord', { 334 method: 'POST', 335 token, 336 body: { repo, collection, rkey, record }, 337 }) 338 }, 339 340 async deleteRecord(token: string, repo: string, collection: string, rkey: string): Promise<void> { 341 await xrpc('com.atproto.repo.deleteRecord', { 342 method: 'POST', 343 token, 344 body: { repo, collection, rkey }, 345 }) 346 }, 347}