this repo has no description
1const API_BASE = '/xrpc' 2 3export class ApiError extends Error { 4 public did?: string 5 constructor(public status: number, public error: string, message: string, did?: string) { 6 super(message) 7 this.name = 'ApiError' 8 this.did = did 9 } 10} 11 12async function xrpc<T>(method: string, options?: { 13 method?: 'GET' | 'POST' 14 params?: Record<string, string> 15 body?: unknown 16 token?: string 17}): Promise<T> { 18 const { method: httpMethod = 'GET', params, body, token } = options ?? {} 19 let url = `${API_BASE}/${method}` 20 if (params) { 21 const searchParams = new URLSearchParams(params) 22 url += `?${searchParams}` 23 } 24 const headers: Record<string, string> = {} 25 if (token) { 26 headers['Authorization'] = `Bearer ${token}` 27 } 28 if (body) { 29 headers['Content-Type'] = 'application/json' 30 } 31 const res = await fetch(url, { 32 method: httpMethod, 33 headers, 34 body: body ? JSON.stringify(body) : undefined, 35 }) 36 if (!res.ok) { 37 const err = await res.json().catch(() => ({ error: 'Unknown', message: res.statusText })) 38 throw new ApiError(res.status, err.error, err.message, err.did) 39 } 40 return res.json() 41} 42 43export interface Session { 44 did: string 45 handle: string 46 email?: string 47 emailConfirmed?: boolean 48 preferredChannel?: string 49 preferredChannelVerified?: boolean 50 isAdmin?: boolean 51 accessJwt: string 52 refreshJwt: string 53} 54 55export interface AppPassword { 56 name: string 57 createdAt: string 58} 59 60export interface InviteCode { 61 code: string 62 available: number 63 disabled: boolean 64 forAccount: string 65 createdBy: string 66 createdAt: string 67 uses: { usedBy: string; usedAt: string }[] 68} 69 70export type VerificationChannel = 'email' | 'discord' | 'telegram' | 'signal' 71 72export interface CreateAccountParams { 73 handle: string 74 email: string 75 password: string 76 inviteCode?: string 77 verificationChannel?: VerificationChannel 78 discordId?: string 79 telegramUsername?: string 80 signalNumber?: string 81} 82 83export interface CreateAccountResult { 84 handle: string 85 did: string 86 verificationRequired: boolean 87 verificationChannel: string 88} 89 90export interface ConfirmSignupResult { 91 accessJwt: string 92 refreshJwt: string 93 handle: string 94 did: string 95 email?: string 96 emailConfirmed?: boolean 97 preferredChannel?: string 98 preferredChannelVerified?: boolean 99} 100 101export const api = { 102 async createAccount(params: CreateAccountParams): Promise<CreateAccountResult> { 103 return xrpc('com.atproto.server.createAccount', { 104 method: 'POST', 105 body: { 106 handle: params.handle, 107 email: params.email, 108 password: params.password, 109 inviteCode: params.inviteCode, 110 verificationChannel: params.verificationChannel, 111 discordId: params.discordId, 112 telegramUsername: params.telegramUsername, 113 signalNumber: params.signalNumber, 114 }, 115 }) 116 }, 117 118 async confirmSignup(did: string, verificationCode: string): Promise<ConfirmSignupResult> { 119 return xrpc('com.atproto.server.confirmSignup', { 120 method: 'POST', 121 body: { did, verificationCode }, 122 }) 123 }, 124 125 async resendVerification(did: string): Promise<{ success: boolean }> { 126 return xrpc('com.atproto.server.resendVerification', { 127 method: 'POST', 128 body: { did }, 129 }) 130 }, 131 132 async createSession(identifier: string, password: string): Promise<Session> { 133 return xrpc('com.atproto.server.createSession', { 134 method: 'POST', 135 body: { identifier, password }, 136 }) 137 }, 138 139 async getSession(token: string): Promise<Session> { 140 return xrpc('com.atproto.server.getSession', { token }) 141 }, 142 143 async refreshSession(refreshJwt: string): Promise<Session> { 144 return xrpc('com.atproto.server.refreshSession', { 145 method: 'POST', 146 token: refreshJwt, 147 }) 148 }, 149 150 async deleteSession(token: string): Promise<void> { 151 await xrpc('com.atproto.server.deleteSession', { 152 method: 'POST', 153 token, 154 }) 155 }, 156 157 async listAppPasswords(token: string): Promise<{ passwords: AppPassword[] }> { 158 return xrpc('com.atproto.server.listAppPasswords', { token }) 159 }, 160 161 async createAppPassword(token: string, name: string): Promise<{ name: string; password: string; createdAt: string }> { 162 return xrpc('com.atproto.server.createAppPassword', { 163 method: 'POST', 164 token, 165 body: { name }, 166 }) 167 }, 168 169 async revokeAppPassword(token: string, name: string): Promise<void> { 170 await xrpc('com.atproto.server.revokeAppPassword', { 171 method: 'POST', 172 token, 173 body: { name }, 174 }) 175 }, 176 177 async getAccountInviteCodes(token: string): Promise<{ codes: InviteCode[] }> { 178 return xrpc('com.atproto.server.getAccountInviteCodes', { token }) 179 }, 180 181 async createInviteCode(token: string, useCount: number = 1): Promise<{ code: string }> { 182 return xrpc('com.atproto.server.createInviteCode', { 183 method: 'POST', 184 token, 185 body: { useCount }, 186 }) 187 }, 188 189 async requestPasswordReset(email: string): Promise<void> { 190 await xrpc('com.atproto.server.requestPasswordReset', { 191 method: 'POST', 192 body: { email }, 193 }) 194 }, 195 196 async resetPassword(token: string, password: string): Promise<void> { 197 await xrpc('com.atproto.server.resetPassword', { 198 method: 'POST', 199 body: { token, password }, 200 }) 201 }, 202 203 async requestEmailUpdate(token: string): Promise<{ tokenRequired: boolean }> { 204 return xrpc('com.atproto.server.requestEmailUpdate', { 205 method: 'POST', 206 token, 207 }) 208 }, 209 210 async updateEmail(token: string, email: string, emailToken?: string): Promise<void> { 211 await xrpc('com.atproto.server.updateEmail', { 212 method: 'POST', 213 token, 214 body: { email, token: emailToken }, 215 }) 216 }, 217 218 async updateHandle(token: string, handle: string): Promise<void> { 219 await xrpc('com.atproto.identity.updateHandle', { 220 method: 'POST', 221 token, 222 body: { handle }, 223 }) 224 }, 225 226 async requestAccountDelete(token: string): Promise<void> { 227 await xrpc('com.atproto.server.requestAccountDelete', { 228 method: 'POST', 229 token, 230 }) 231 }, 232 233 async deleteAccount(did: string, password: string, deleteToken: string): Promise<void> { 234 await xrpc('com.atproto.server.deleteAccount', { 235 method: 'POST', 236 body: { did, password, token: deleteToken }, 237 }) 238 }, 239 240 async describeServer(): Promise<{ 241 availableUserDomains: string[] 242 inviteCodeRequired: boolean 243 links?: { privacyPolicy?: string; termsOfService?: string } 244 }> { 245 return xrpc('com.atproto.server.describeServer') 246 }, 247 248 async getNotificationPrefs(token: string): Promise<{ 249 preferredChannel: string 250 email: string 251 discordId: string | null 252 discordVerified: boolean 253 telegramUsername: string | null 254 telegramVerified: boolean 255 signalNumber: string | null 256 signalVerified: boolean 257 }> { 258 return xrpc('com.bspds.account.getNotificationPrefs', { token }) 259 }, 260 261 async updateNotificationPrefs(token: string, prefs: { 262 preferredChannel?: string 263 discordId?: string 264 telegramUsername?: string 265 signalNumber?: string 266 }): Promise<{ success: boolean }> { 267 return xrpc('com.bspds.account.updateNotificationPrefs', { 268 method: 'POST', 269 token, 270 body: prefs, 271 }) 272 }, 273 274 async confirmChannelVerification(token: string, channel: string, code: string): Promise<{ success: boolean }> { 275 return xrpc('com.bspds.account.confirmChannelVerification', { 276 method: 'POST', 277 token, 278 body: { channel, code }, 279 }) 280 }, 281 282 async getNotificationHistory(token: string): Promise<{ 283 notifications: Array<{ 284 createdAt: string 285 channel: string 286 notificationType: string 287 status: string 288 subject: string | null 289 body: string 290 }> 291 }> { 292 return xrpc('com.bspds.account.getNotificationHistory', { token }) 293 }, 294 295 async getServerStats(token: string): Promise<{ 296 userCount: number 297 repoCount: number 298 recordCount: number 299 blobStorageBytes: number 300 }> { 301 return xrpc('com.bspds.admin.getServerStats', { token }) 302 }, 303 304 async changePassword(token: string, currentPassword: string, newPassword: string): Promise<void> { 305 await xrpc('com.bspds.account.changePassword', { 306 method: 'POST', 307 token, 308 body: { currentPassword, newPassword }, 309 }) 310 }, 311 312 async listSessions(token: string): Promise<{ 313 sessions: Array<{ 314 id: string 315 createdAt: string 316 expiresAt: string 317 isCurrent: boolean 318 }> 319 }> { 320 return xrpc('com.bspds.account.listSessions', { token }) 321 }, 322 323 async revokeSession(token: string, sessionId: string): Promise<void> { 324 await xrpc('com.bspds.account.revokeSession', { 325 method: 'POST', 326 token, 327 body: { sessionId }, 328 }) 329 }, 330 331 async searchAccounts(token: string, options?: { 332 handle?: string 333 cursor?: string 334 limit?: number 335 }): Promise<{ 336 cursor?: string 337 accounts: Array<{ 338 did: string 339 handle: string 340 email?: string 341 indexedAt: string 342 emailConfirmedAt?: string 343 deactivatedAt?: string 344 }> 345 }> { 346 const params: Record<string, string> = {} 347 if (options?.handle) params.handle = options.handle 348 if (options?.cursor) params.cursor = options.cursor 349 if (options?.limit) params.limit = String(options.limit) 350 return xrpc('com.atproto.admin.searchAccounts', { token, params }) 351 }, 352 353 async getInviteCodes(token: string, options?: { 354 sort?: 'recent' | 'usage' 355 cursor?: string 356 limit?: number 357 }): Promise<{ 358 cursor?: string 359 codes: Array<{ 360 code: string 361 available: number 362 disabled: boolean 363 forAccount: string 364 createdBy: string 365 createdAt: string 366 uses: Array<{ usedBy: string; usedAt: string }> 367 }> 368 }> { 369 const params: Record<string, string> = {} 370 if (options?.sort) params.sort = options.sort 371 if (options?.cursor) params.cursor = options.cursor 372 if (options?.limit) params.limit = String(options.limit) 373 return xrpc('com.atproto.admin.getInviteCodes', { token, params }) 374 }, 375 376 async disableInviteCodes(token: string, codes?: string[], accounts?: string[]): Promise<void> { 377 await xrpc('com.atproto.admin.disableInviteCodes', { 378 method: 'POST', 379 token, 380 body: { codes, accounts }, 381 }) 382 }, 383 384 async getAccountInfo(token: string, did: string): Promise<{ 385 did: string 386 handle: string 387 email?: string 388 indexedAt: string 389 emailConfirmedAt?: string 390 invitesDisabled?: boolean 391 deactivatedAt?: string 392 }> { 393 return xrpc('com.atproto.admin.getAccountInfo', { token, params: { did } }) 394 }, 395 396 async disableAccountInvites(token: string, account: string): Promise<void> { 397 await xrpc('com.atproto.admin.disableAccountInvites', { 398 method: 'POST', 399 token, 400 body: { account }, 401 }) 402 }, 403 404 async enableAccountInvites(token: string, account: string): Promise<void> { 405 await xrpc('com.atproto.admin.enableAccountInvites', { 406 method: 'POST', 407 token, 408 body: { account }, 409 }) 410 }, 411 412 async adminDeleteAccount(token: string, did: string): Promise<void> { 413 await xrpc('com.atproto.admin.deleteAccount', { 414 method: 'POST', 415 token, 416 body: { did }, 417 }) 418 }, 419 420 async describeRepo(token: string, repo: string): Promise<{ 421 handle: string 422 did: string 423 didDoc: unknown 424 collections: string[] 425 handleIsCorrect: boolean 426 }> { 427 return xrpc('com.atproto.repo.describeRepo', { 428 token, 429 params: { repo }, 430 }) 431 }, 432 433 async listRecords(token: string, repo: string, collection: string, options?: { 434 limit?: number 435 cursor?: string 436 reverse?: boolean 437 }): Promise<{ 438 records: Array<{ uri: string; cid: string; value: unknown }> 439 cursor?: string 440 }> { 441 const params: Record<string, string> = { repo, collection } 442 if (options?.limit) params.limit = String(options.limit) 443 if (options?.cursor) params.cursor = options.cursor 444 if (options?.reverse) params.reverse = 'true' 445 return xrpc('com.atproto.repo.listRecords', { token, params }) 446 }, 447 448 async getRecord(token: string, repo: string, collection: string, rkey: string): Promise<{ 449 uri: string 450 cid: string 451 value: unknown 452 }> { 453 return xrpc('com.atproto.repo.getRecord', { 454 token, 455 params: { repo, collection, rkey }, 456 }) 457 }, 458 459 async createRecord(token: string, repo: string, collection: string, record: unknown, rkey?: string): Promise<{ 460 uri: string 461 cid: string 462 }> { 463 return xrpc('com.atproto.repo.createRecord', { 464 method: 'POST', 465 token, 466 body: { repo, collection, record, rkey }, 467 }) 468 }, 469 470 async putRecord(token: string, repo: string, collection: string, rkey: string, record: unknown): Promise<{ 471 uri: string 472 cid: string 473 }> { 474 return xrpc('com.atproto.repo.putRecord', { 475 method: 'POST', 476 token, 477 body: { repo, collection, rkey, record }, 478 }) 479 }, 480 481 async deleteRecord(token: string, repo: string, collection: string, rkey: string): Promise<void> { 482 await xrpc('com.atproto.repo.deleteRecord', { 483 method: 'POST', 484 token, 485 body: { repo, collection, rkey }, 486 }) 487 }, 488}