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

Configure Feed

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

docs: add links to other functions

kacaii.dev (Jul 14, 2026, 4:50 PM -0300) f71c2608 5a235373

+85 -24
+3
README.md
··· 18 18 19 19 ```sh 20 20 gleam add possum gleam_http gleam_json 21 + 22 + # Optional extensions 23 + gleam add possum_tangled 21 24 ``` 22 25 23 26 ### Decentralized Identifiers (DIDs)
-3
gleam.toml
··· 6 6 repository = { type = "tangled", user = "kacaii.dev", repo = "possum" } 7 7 8 8 links = [ 9 - { title = "AT Protocol", href = "https://atproto.com/" }, 10 - { title = "Bluesky HTTP API Reference", href = "https://endpoints.bsky.app/" }, 11 - { title = "Blogpost: A Social File System", href = "https://overreacted.io/a-social-filesystem/" }, 12 9 { title = "possum/tangled", href = "https://tangled.org/kacaii.dev/possum-tangled" }, 13 10 ] 14 11
+43 -18
src/possum.gleam
··· 8 8 //// general account management interfaces such as the OAuth login screen. 9 9 //// PDSes actively sync their data repos with Relays. 10 10 //// 11 - //// ## Lexicon 12 - //// 13 - //// Lexicon is a schema language. It's used in the Atmosphere to describe data 14 - //// records and HTTP APIs. Functionally it's very similar to JSON-Schema and OpenAPI. 15 - //// Lexicon's sole purpose is to help developers build compatible software. 16 - //// 17 11 //// ## Record Keys 18 12 //// 19 13 //// A record key (sometimes shortened to "rkey") is used to name and reference an individual ··· 96 90 /// ``` 97 91 /// 98 92 /// Documentation: [DID PLC Directory](https://web.plc.directory/) 93 + /// 94 + /// See also: [did](possum/did.html), [did.parse](possum/did.html#parse) 99 95 pub fn get_plc_data(did: did.Did) -> request.Request(String) { 100 96 request.Request( 101 97 method: http.Get, ··· 140 136 ) 141 137 } 142 138 143 - /// Resolves an atproto handle (hostname) to a DID. 139 + /// Resolves an atproto handle (hostname) to a [DID](possum/did.html#Did). 144 140 /// Does not necessarily bi-directionally verify against the the DID document. 145 141 /// 146 142 /// You can use projects like [Slingshot](https://slingshot.microcosm.blue) ··· 149 145 /// ## Examples 150 146 /// 151 147 /// ```gleam 152 - /// import gleam/http/request 153 148 /// import possum/handle 154 149 /// import possum 155 150 /// ··· 166 161 /// ``` 167 162 /// 168 163 /// Endpoint Docs: [/xrpc/com.atproto.identity.resolveHandle](https://endpoints.bsky.app/#bluesky-app/tag/comatprotoidentity/GET/xrpc/com.atproto.identity.resolveHandle) 164 + /// 165 + /// See also: [did](possum/did.html), [did.parse](possum/did.html#parse) 169 166 pub fn resolve_handle( 170 167 handle: handle.Handle, 171 168 pds host: String, ··· 231 228 /// ``` 232 229 /// 233 230 /// Endpoint Docs: [/xrpc/com.atproto.server.createSession](https://endpoints.bsky.app/#bluesky-app/tag/comatprotoserver/POST/xrpc/com.atproto.server.createSession) 231 + /// 232 + /// See also: [did.parse](possum/did.html#parse), [refresh_session](#refresh_session) 234 233 pub fn create_session( 235 234 did: did.Did, 236 235 pds host: String, ··· 298 297 /// ``` 299 298 /// 300 299 /// Endpoint Docs: [/xrpc/com.atproto.server.refreshSession](https://endpoints.bsky.app/#bluesky-app/tag/comatprotoserver/POST/xrpc/com.atproto.server.refreshSession) 300 + /// 301 + /// See also: [create_session](#create_session), [get_session_info](#get_session_info) 301 302 pub fn refresh_session( 302 303 token: String, 303 304 pds host: String, ··· 316 317 } 317 318 318 319 /// Get information about the current auth session. 319 - /// Requires auth. 320 320 /// 321 321 /// ## Examples 322 322 /// ··· 345 345 /// ``` 346 346 /// 347 347 /// Endpoint Docs: [/xrpc/com.atproto.server.getSession](https://endpoints.bsky.app/#bluesky-app/tag/comatprotoserver/POST/xrpc/com.atproto.server.getSession) 348 + /// 349 + /// See also: [create_session](#create_session), [refresh_session](#refresh_session) 348 350 pub fn get_session_info(pds host: String) -> request.Request(String) { 349 351 request.Request( 350 352 method: http.Get, ··· 358 360 ) 359 361 } 360 362 361 - /// Include a access token in the request's headers. 362 - /// Tokens can be acquired with `create_session`. 363 + /// Include a access token in the request's headers 364 + /// Tokens can be acquired with [create_session](#create_session) 363 365 /// 364 366 /// ## Examples 365 367 /// ··· 374 376 /// assert request.headers != [] 375 377 /// ``` 376 378 /// 379 + /// See also: [create_session](#create_session) 377 380 pub fn authorized( 378 381 request: request.Request(String), 379 382 access_token token: String, ··· 381 384 request.prepend_header(request, "authorization", "bearer " <> token) 382 385 } 383 386 384 - /// Get information about an account and repository, including the list of collections. 387 + /// Get information about a user's repository, 388 + /// including the list of collections. 385 389 /// 386 390 /// ## Examples 387 391 /// ··· 391 395 /// import possum 392 396 /// 393 397 /// let assert Ok(did) = did.parse("did:plc:ewvi7nxzyoun6zhxrhs64oiz") 398 + /// 394 399 /// let request = 395 400 /// possum.describe_repository(did, pds: "personal.data-server.pds") 396 401 /// ``` ··· 410 415 /// ``` 411 416 /// 412 417 /// Endpoint Docs: [/xrpc/com.atproto.repo.describeRepo](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/GET/xrpc/com.atproto.repo.describeRepo) 418 + /// 419 + /// See also: [did](possum/did.html), [did.parse](possum/did.html#parse) 413 420 pub fn describe_repository( 414 421 did: did.Did, 415 422 pds host: String, ··· 479 486 /// ``` 480 487 /// 481 488 /// Endpoint Docs: [/xrpc/com.atproto.repo.createRecord](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/POST/xrpc/com.atproto.repo.createRecord) 489 + /// 490 + /// See also: [did.parse](possum/did.html#parse), [nsid.parse](possum/nsid.html#parse), [authorized](#authorized) 482 491 pub fn create_record( 483 492 did: did.Did, 484 493 pds host: String, ··· 530 539 /// for easy access to cached data. 531 540 /// 532 541 /// ```gleam 533 - /// import gleam/http/request 534 542 /// import possum/did 535 543 /// import possum/nsid 536 544 /// import possum ··· 560 568 /// ``` 561 569 /// 562 570 /// Endpoint Docs: [/xrpc/com.atproto.repo.getRecord](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/GET/xrpc/com.atproto.repo.getRecord) 563 - /// Documentation: [atproto.com](https://atproto.com/specs/record-key) 571 + /// 572 + /// See also: [did.parse](possum/did.html#parse), [nsid.parse](possum/nsid.html#parse) 564 573 pub fn get_record( 565 574 did: did.Did, 566 575 pds host: String, ··· 597 606 /// ## Examples 598 607 /// 599 608 /// ```gleam 600 - /// import gleam/http/request 601 609 /// import possum/did 602 610 /// import possum/nsid 603 611 /// import possum ··· 632 640 /// ``` 633 641 /// 634 642 /// Endpoint Docs: [/xrpc/com.atproto.repo.listRecords](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/GET/xrpc/com.atproto.repo.listRecords) 643 + /// 644 + /// See also: [did.parse](possum/did.html#parse), [nsid.parse](possum/nsid.html#parse) 635 645 pub fn list_records( 636 646 did: did.Did, 637 647 pds host: String, ··· 685 695 /// ## Examples 686 696 /// 687 697 /// ```gleam 688 - /// import gleam/http/request 689 698 /// import possum/did 690 699 /// import possum/nsid 691 700 /// import possum ··· 717 726 /// ``` 718 727 /// 719 728 /// Endpoint Docs: [/xrpc/com.atproto.repo.deleteRecord](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/POST/xrpc/com.atproto.repo.deleteRecord) 729 + /// 730 + /// See also: [did.parse](possum/did.html#parse), [nsid.parse](possum/nsid.html#parse), [create_session](#create_session) 720 731 pub fn delete_record( 721 732 did: did.Did, 722 733 pds host: String, ··· 773 784 /// ## Examples 774 785 /// 775 786 /// ```gleam 776 - /// import gleam/http/request 777 787 /// import possum/did 778 788 /// import possum/nsid 779 789 /// import possum ··· 810 820 /// ``` 811 821 /// 812 822 /// Endpoint Docs: [/xrpc/com.atproto.repo.putRecord](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/POST/xrpc/com.atproto.repo.putRecord) 823 + /// 824 + /// See also: [did.parse](possum/did.html#parse), [nsid.parse](possum/nsid.html#parse), [create_session](#create_session) 813 825 pub fn put_record( 814 826 did: did.Did, 815 827 pds host: String, ··· 861 873 /// Returns the full blob as originally uploaded. 862 874 /// Does not require auth; implemented by PDS. 863 875 /// 876 + /// ## Examples 877 + /// 878 + /// ```gleam 879 + /// import possum/did 880 + /// import possum 881 + /// 882 + /// let assert Ok(did) = did.parse("did:plc:k5vecqzf4d5mdvkcu3mx6l5g") 883 + /// 884 + /// let request = possum.get_blog(did, "wibble-wobble", pds: "personal.data-server.pds") 885 + /// ``` 886 + /// 864 887 /// Endpoint Docs: [/xrpc/com.atproto.sync.getBlob](https://endpoints.bsky.app/#bluesky-app/tag/comatprotosync/GET/xrpc/com.atproto.sync.getBlob) 888 + /// 889 + /// See also: [did](possum/did.html#parse) 865 890 pub fn get_blob( 866 891 did: did.Did, 867 - cid: String, 892 + cid cid: String, 868 893 pds host: String, 869 894 ) -> request.Request(BitArray) { 870 895 let query = [#("did", did.to_string(did)), #("cid", cid)]
+12
src/possum/at_uri.gleam
··· 40 40 } 41 41 42 42 /// A URI scheme for addressing atproto repository data. 43 + /// 44 + /// See also: [parse](#parse) 43 45 pub opaque type AtUri { 44 46 AtUri( 45 47 /// Identifier, can be a DID or a Handle ··· 63 65 /// 64 66 /// assert at_uri.authority(at_uri) == "did:plc:vwzwgnygau7ed7b7wt5ux7y2" 65 67 /// ``` 68 + /// 69 + /// See also: [Aturi](#AtUri) 66 70 pub fn authority(self: AtUri) -> Authority { 67 71 self.authority 68 72 } ··· 79 83 /// 80 84 /// assert at_uri.collection(at_uri) == "app.bsky.feed.post" 81 85 /// ``` 86 + /// 87 + /// See also: [Aturi](#AtUri) 82 88 pub fn collection(self: AtUri) -> String { 83 89 self.collection 84 90 } ··· 95 101 /// 96 102 /// assert at_uri.rkey(at_uri) == "3k5nobkf2w72g" 97 103 /// ``` 104 + /// 105 + /// See also: [Aturi](#AtUri) 98 106 pub fn rkey(self: AtUri) -> String { 99 107 self.rkey 100 108 } ··· 112 120 /// let string = "at://did:plc:vwzwgnygau7ed7b7wt5ux7y2/app.bsky.feed.post/3k5nobkf2w72g" 113 121 /// let assert Ok(at_uri) = at_uri.parse(string) 114 122 /// ``` 123 + /// 124 + /// See also: [Aturi](#AtUri) 115 125 pub fn parse(content: String) -> Result(AtUri, ParseError) { 116 126 use value <- result.try(case content { 117 127 "at://" <> rest -> Ok(rest) ··· 183 193 /// let assert Ok(at_uri) = at_uri.parse(string) 184 194 /// assert at_uri.to_string(at_uri) == string 185 195 /// ``` 196 + /// 197 + /// See also: [Aturi](#AtUri) 186 198 pub fn to_string(self: AtUri) -> String { 187 199 let host = case self.authority { 188 200 Handle(value:) -> handle.to_string(value)
+15 -3
src/possum/did.gleam
··· 30 30 /// identifiers. An example DID is `did:plc:ewvi7nxzyoun6zhxrhs64oiz`. 31 31 /// 32 32 /// Documentation: [Decentralized Identifiers](https://atproto.com/specs/did) 33 + /// 34 + /// See also: [parse](#parse) 33 35 pub opaque type Did { 34 36 Did(method: Method, identifier: String) 35 37 } ··· 39 41 /// ## Examples 40 42 /// 41 43 /// ```gleam 44 + /// import possum/did 45 + /// 42 46 /// let assert Ok(did) = did.parse("did:plc:k5vecqzf4d5mdvkcu3mx6l5g") 43 - /// let method = possum.method(did) 47 + /// let method = did.method(did) 44 48 /// 45 49 /// assert method == did.Plc 46 50 /// ``` 51 + /// 52 + /// See also: [Did](#Did) 47 53 pub fn method(self: Did) -> Method { 48 54 self.method 49 55 } ··· 63 69 /// 64 70 /// assert identifier == "k5vecqzf4d5mdvkcu3mx6l5g" 65 71 /// ``` 72 + /// 73 + /// See also: [Did](#Did) 66 74 pub fn indentifer(self: Did) -> String { 67 75 self.identifier 68 76 } 69 77 70 - /// Convert a DID to a string. 78 + /// Convert a [DID](#Did) to a string. 71 79 /// 72 80 /// ## Examples 73 81 /// ··· 79 87 /// 80 88 /// assert string == "did:plc:k5vecqzf4d5mdvkcu3mx6l5g" 81 89 /// ``` 90 + /// 91 + /// See also: [Did](#Did) 82 92 pub fn to_string(self: Did) -> String { 83 93 case self.method { 84 94 Plc -> "did:plc:" <> self.identifier ··· 117 127 Web 118 128 } 119 129 120 - /// Parse a string into a valid `Did` type 130 + /// Parse a string into a valid [Did](#Did) type 121 131 /// If the value is not a valid string then an error is returned. 122 132 /// 123 133 /// ## Examples ··· 128 138 /// let string = "did:plc:k5vecqzf4d5mdvkcu3mx6l5g" 129 139 /// let assert Ok(did) = did.parse(string) 130 140 /// ``` 141 + /// 142 + /// See also: [Did](#Did) 131 143 pub fn parse(content: String) -> Result(Did, ParseError) { 132 144 use with <- result.try( 133 145 regexp.from_string(pattern)
+12
src/possum/nsid.gleam
··· 5 5 //// in reverse domain-name order, followed by an additional name segment. 6 6 //// The hostname part is the **domain authority**, and the final segment is the **name**. 7 7 //// 8 + //// ## Lexicon 9 + //// 10 + //// Lexicon is a schema language. It's used in the Atmosphere to describe data 11 + //// records and HTTP APIs. Functionally it's very similar to JSON-Schema and OpenAPI. 12 + //// Lexicon's sole purpose is to help developers build compatible software. 13 + //// 8 14 //// Documentation: [Namespaced Identifiers](https://atproto.com/specs/nsid) 9 15 10 16 import gleam/regexp ··· 21 27 } 22 28 23 29 /// A specification for global semantic IDs. 30 + /// 31 + /// See also: [parse](#parse) 24 32 pub opaque type Nsid { 25 33 Nsid(value: String) 26 34 } ··· 37 45 /// let assert Ok(nsid) = nsid.parse(string) 38 46 /// assert nsid.to_string(nsid) == string 39 47 /// ``` 48 + /// 49 + /// See also: [Nsid](#Nsid) 40 50 pub fn to_string(nsid: Nsid) -> String { 41 51 nsid.value 42 52 } ··· 52 62 /// let string = "com.atproto.sync.getRecord." 53 63 /// let assert Ok(nsid) = nsid.parse(string) 54 64 /// ``` 65 + /// 66 + /// See also: [Nsid](#Nsid) 55 67 pub fn parse(content: String) -> Result(Nsid, ParseError) { 56 68 use with <- result.try( 57 69 regexp.from_string(pattern)