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