๐Ÿ€ ATproto library for gleam
atproto library gleam
35

Configure Feed

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

possum: use a parsed did.Did instead of a String

kacaii.dev (Jun 30, 2026, 5:18 PM -0300) ae44f47b 1d62879f

+32 -28
+12 -22
src/possum.gleam
··· 14 14 //// records and HTTP APIs. Functionally it's very similar to JSON-Schema and OpenAPI. 15 15 //// Lexicon's sole purpose is to help developers build compatible software. 16 16 //// 17 - //// ## DID (Decentralized ID) 18 - //// 19 - //// DIDs, or Decentralized IDentifiers, are universally-unique identifiers which 20 - //// represent data repos. They are permanent and non-human-readable. 21 - //// DIDs are a W3C specification. The AT Protocol currently supports 22 - //// did:web and did:plc, two different DID methods. 23 - //// 24 - //// DIDs resolve to documents which contain metadata about a repo, 25 - //// including the address of the repo's PDS, the repo's handles, 26 - //// and the public signing keys. 27 - //// 28 17 //// ## Record Keys 29 18 //// 30 19 //// A record key (sometimes shortened to "rkey") is used to name and reference an individual ··· 42 31 import gleam/int 43 32 import gleam/json 44 33 import gleam/option 34 + import possum/did 45 35 46 36 /// Documentation: [/xrpc/com.atproto.repo](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo) 47 37 const com_atproto_repo = "xrpc/com.atproto.repo" ··· 96 86 /// Documentation: [DID PLC Directory](https://web.plc.directory/) 97 87 pub fn get_plc_data( 98 88 request: request.Request(_), 99 - did: String, 89 + did: did.Did, 100 90 ) -> request.Request(_) { 101 91 request 102 92 |> request.set_method(http.Get) 103 93 |> request.set_host("plc.directory") 104 - |> request.set_path(did <> "/data") 94 + |> request.set_path(did.to_string(did) <> "/data") 105 95 } 106 96 107 97 /// Resolves a handle to a DID using a HTTPS `/.well-known/` URL path, ··· 211 201 /// Endpoint Docs: [/xrpc/com.atproto.server.createSession](https://endpoints.bsky.app/#bluesky-app/tag/comatprotoserver/POST/xrpc/com.atproto.server.createSession) 212 202 pub fn create_session( 213 203 request: request.Request(_), 214 - did: String, 204 + did: did.Did, 215 205 app_password app_password: String, 216 206 allow_takendown allow_takendown: option.Option(Bool), 217 207 auth_factor_token auth_factor_token: option.Option(String), 218 208 ) -> request.Request(_) { 219 209 let values = [ 220 - #("identifier", json.string(did)), 210 + #("identifier", json.string(did.to_string(did))), 221 211 #("password", json.string(app_password)), 222 212 ] 223 213 ··· 376 366 /// Endpoint Docs: [/xrpc/com.atproto.repo.describeRepo](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/GET/xrpc/com.atproto.repo.describeRepo) 377 367 pub fn describe_repository( 378 368 request: request.Request(_), 379 - did: String, 369 + did: did.Did, 380 370 ) -> request.Request(_) { 381 371 request 382 372 |> request.set_method(http.Get) 383 373 |> request.set_path(com_atproto_repo <> ".describeRepo") 384 - |> request.set_query([#("repo", did)]) 374 + |> request.set_query([#("repo", did.to_string(did))]) 385 375 } 386 376 387 377 /// Get a single record from a repository. Does not require auth. ··· 426 416 /// Documentation: [atproto.com](https://atproto.com/specs/record-key) 427 417 pub fn get_record( 428 418 request: request.Request(_), 429 - did: String, 419 + did: did.Did, 430 420 rkey rkey: String, 431 421 collection collection: String, 432 422 cid cid: option.Option(String), 433 423 ) -> request.Request(_) { 434 424 let query = [ 435 - #("repo", did), 425 + #("repo", did.to_string(did)), 436 426 #("rkey", rkey), 437 427 #("collection", collection), 438 428 ] ··· 486 476 /// Endpoint Docs: [/xrpc/com.atproto.repo.listRecords](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/GET/xrpc/com.atproto.repo.listRecords) 487 477 pub fn list_records( 488 478 request: request.Request(_), 489 - did: String, 479 + did: did.Did, 490 480 collection collection: String, 491 481 limit limit: option.Option(Int), 492 482 cursor cursor: option.Option(String), 493 483 reverse reverse: option.Option(Bool), 494 484 ) -> request.Request(_) { 495 485 let query = [ 496 - #("repo", did), 486 + #("repo", did.to_string(did)), 497 487 #("collection", collection), 498 488 ] 499 489 ··· 541 531 /// Documentation: [standard.site](https://standard.site/) 542 532 pub fn list_standard_documents( 543 533 request: request.Request(_), 544 - did: String, 534 + did: did.Did, 545 535 limit limit: option.Option(Int), 546 536 ) -> request.Request(_) { 547 537 list_records(
+15 -4
src/possum/did.gleam
··· 1 - import gleam/regexp as regex 1 + //// ## DID (Decentralized ID) 2 + //// 3 + //// DIDs, or Decentralized IDentifiers, are universally-unique identifiers which 4 + //// represent data repos. They are permanent and non-human-readable. 5 + //// DIDs are a W3C specification. The AT Protocol currently supports 6 + //// did:web and did:plc, two different DID methods. 7 + //// 8 + //// DIDs resolve to documents which contain metadata about a repo, 9 + //// including the address of the repo's PDS, the repo's handles, 10 + //// and the public signing keys. 11 + 12 + import gleam/regexp 2 13 import gleam/result 3 14 4 - const pattern = "/^did:[a-z]+:[a-zA-Z0-9._:%-]*[a-zA-Z0-9._-]$/" 15 + const pattern = "^did:[a-z]+:[a-zA-Z0-9._:%-]*[a-zA-Z0-9._-]$" 5 16 6 17 pub type DidError { 7 18 InvalidRegexPattern(pattern: String) ··· 92 103 93 104 pub fn new(content: String) -> Result(Did, DidError) { 94 105 use with <- result.try( 95 - regex.from_string(pattern) 106 + regexp.from_string(pattern) 96 107 |> result.replace_error(InvalidRegexPattern(pattern:)), 97 108 ) 98 109 99 - use value <- result.try(case regex.check(with:, content:) { 110 + use value <- result.try(case regexp.check(with:, content:) { 100 111 True -> Ok(content) 101 112 False -> Error(InvalidFormat(content)) 102 113 })
+5 -2
test/possum_test.gleam
··· 6 6 import gleeunit 7 7 import global_value 8 8 import possum 9 + import possum/did 9 10 10 11 pub fn main() -> Nil { 11 12 gleeunit.main() ··· 16 17 const plc_directory = "plc.directory" 17 18 18 19 pub type Context { 19 - Context(handle: String, did: String, pds: String) 20 + Context(handle: String, did: did.Did, pds: String) 20 21 } 21 22 22 23 fn global_data() -> Context { ··· 29 30 |> possum.resolve_handle(handle) 30 31 |> httpc.send 31 32 32 - let assert Ok("did:plc:" <> _rest as did) = 33 + let assert Ok(body) = 33 34 json.parse(did_response.body, decode.at(["did"], decode.string)) 35 + 36 + let assert Ok(did) = did.new(body) 34 37 35 38 let assert Ok(pds_response) = 36 39 request.new()