···66repository = { type = "tangled", user = "kacaii.dev", repo = "possum" }
7788links = [
99- { title = "AT Protocol", href = "https://atproto.com/" },
1010- { title = "Bluesky HTTP API Reference", href = "https://endpoints.bsky.app/" },
1111- { title = "Blogpost: A Social File System", href = "https://overreacted.io/a-social-filesystem/" },
129 { title = "possum/tangled", href = "https://tangled.org/kacaii.dev/possum-tangled" },
1310]
1411
+43-18
src/possum.gleam
···88//// general account management interfaces such as the OAuth login screen.
99//// PDSes actively sync their data repos with Relays.
1010////
1111-//// ## Lexicon
1212-////
1313-//// Lexicon is a schema language. It's used in the Atmosphere to describe data
1414-//// records and HTTP APIs. Functionally it's very similar to JSON-Schema and OpenAPI.
1515-//// Lexicon's sole purpose is to help developers build compatible software.
1616-////
1711//// ## Record Keys
1812////
1913//// A record key (sometimes shortened to "rkey") is used to name and reference an individual
···9690/// ```
9791///
9892/// Documentation: [DID PLC Directory](https://web.plc.directory/)
9393+///
9494+/// See also: [did](possum/did.html), [did.parse](possum/did.html#parse)
9995pub fn get_plc_data(did: did.Did) -> request.Request(String) {
10096 request.Request(
10197 method: http.Get,
···140136 )
141137}
142138143143-/// Resolves an atproto handle (hostname) to a DID.
139139+/// Resolves an atproto handle (hostname) to a [DID](possum/did.html#Did).
144140/// Does not necessarily bi-directionally verify against the the DID document.
145141///
146142/// You can use projects like [Slingshot](https://slingshot.microcosm.blue)
···149145/// ## Examples
150146///
151147/// ```gleam
152152-/// import gleam/http/request
153148/// import possum/handle
154149/// import possum
155150///
···166161/// ```
167162///
168163/// Endpoint Docs: [/xrpc/com.atproto.identity.resolveHandle](https://endpoints.bsky.app/#bluesky-app/tag/comatprotoidentity/GET/xrpc/com.atproto.identity.resolveHandle)
164164+///
165165+/// See also: [did](possum/did.html), [did.parse](possum/did.html#parse)
169166pub fn resolve_handle(
170167 handle: handle.Handle,
171168 pds host: String,
···231228/// ```
232229///
233230/// Endpoint Docs: [/xrpc/com.atproto.server.createSession](https://endpoints.bsky.app/#bluesky-app/tag/comatprotoserver/POST/xrpc/com.atproto.server.createSession)
231231+///
232232+/// See also: [did.parse](possum/did.html#parse), [refresh_session](#refresh_session)
234233pub fn create_session(
235234 did: did.Did,
236235 pds host: String,
···298297/// ```
299298///
300299/// Endpoint Docs: [/xrpc/com.atproto.server.refreshSession](https://endpoints.bsky.app/#bluesky-app/tag/comatprotoserver/POST/xrpc/com.atproto.server.refreshSession)
300300+///
301301+/// See also: [create_session](#create_session), [get_session_info](#get_session_info)
301302pub fn refresh_session(
302303 token: String,
303304 pds host: String,
···316317}
317318318319/// Get information about the current auth session.
319319-/// Requires auth.
320320///
321321/// ## Examples
322322///
···345345/// ```
346346///
347347/// Endpoint Docs: [/xrpc/com.atproto.server.getSession](https://endpoints.bsky.app/#bluesky-app/tag/comatprotoserver/POST/xrpc/com.atproto.server.getSession)
348348+///
349349+/// See also: [create_session](#create_session), [refresh_session](#refresh_session)
348350pub fn get_session_info(pds host: String) -> request.Request(String) {
349351 request.Request(
350352 method: http.Get,
···358360 )
359361}
360362361361-/// Include a access token in the request's headers.
362362-/// Tokens can be acquired with `create_session`.
363363+/// Include a access token in the request's headers
364364+/// Tokens can be acquired with [create_session](#create_session)
363365///
364366/// ## Examples
365367///
···374376/// assert request.headers != []
375377/// ```
376378///
379379+/// See also: [create_session](#create_session)
377380pub fn authorized(
378381 request: request.Request(String),
379382 access_token token: String,
···381384 request.prepend_header(request, "authorization", "bearer " <> token)
382385}
383386384384-/// Get information about an account and repository, including the list of collections.
387387+/// Get information about a user's repository,
388388+/// including the list of collections.
385389///
386390/// ## Examples
387391///
···391395/// import possum
392396///
393397/// let assert Ok(did) = did.parse("did:plc:ewvi7nxzyoun6zhxrhs64oiz")
398398+///
394399/// let request =
395400/// possum.describe_repository(did, pds: "personal.data-server.pds")
396401/// ```
···410415/// ```
411416///
412417/// Endpoint Docs: [/xrpc/com.atproto.repo.describeRepo](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/GET/xrpc/com.atproto.repo.describeRepo)
418418+///
419419+/// See also: [did](possum/did.html), [did.parse](possum/did.html#parse)
413420pub fn describe_repository(
414421 did: did.Did,
415422 pds host: String,
···479486/// ```
480487///
481488/// Endpoint Docs: [/xrpc/com.atproto.repo.createRecord](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/POST/xrpc/com.atproto.repo.createRecord)
489489+///
490490+/// See also: [did.parse](possum/did.html#parse), [nsid.parse](possum/nsid.html#parse), [authorized](#authorized)
482491pub fn create_record(
483492 did: did.Did,
484493 pds host: String,
···530539/// for easy access to cached data.
531540///
532541/// ```gleam
533533-/// import gleam/http/request
534542/// import possum/did
535543/// import possum/nsid
536544/// import possum
···560568/// ```
561569///
562570/// Endpoint Docs: [/xrpc/com.atproto.repo.getRecord](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/GET/xrpc/com.atproto.repo.getRecord)
563563-/// Documentation: [atproto.com](https://atproto.com/specs/record-key)
571571+///
572572+/// See also: [did.parse](possum/did.html#parse), [nsid.parse](possum/nsid.html#parse)
564573pub fn get_record(
565574 did: did.Did,
566575 pds host: String,
···597606/// ## Examples
598607///
599608/// ```gleam
600600-/// import gleam/http/request
601609/// import possum/did
602610/// import possum/nsid
603611/// import possum
···632640/// ```
633641///
634642/// Endpoint Docs: [/xrpc/com.atproto.repo.listRecords](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/GET/xrpc/com.atproto.repo.listRecords)
643643+///
644644+/// See also: [did.parse](possum/did.html#parse), [nsid.parse](possum/nsid.html#parse)
635645pub fn list_records(
636646 did: did.Did,
637647 pds host: String,
···685695/// ## Examples
686696///
687697/// ```gleam
688688-/// import gleam/http/request
689698/// import possum/did
690699/// import possum/nsid
691700/// import possum
···717726/// ```
718727///
719728/// Endpoint Docs: [/xrpc/com.atproto.repo.deleteRecord](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/POST/xrpc/com.atproto.repo.deleteRecord)
729729+///
730730+/// See also: [did.parse](possum/did.html#parse), [nsid.parse](possum/nsid.html#parse), [create_session](#create_session)
720731pub fn delete_record(
721732 did: did.Did,
722733 pds host: String,
···773784/// ## Examples
774785///
775786/// ```gleam
776776-/// import gleam/http/request
777787/// import possum/did
778788/// import possum/nsid
779789/// import possum
···810820/// ```
811821///
812822/// Endpoint Docs: [/xrpc/com.atproto.repo.putRecord](https://endpoints.bsky.app/#bluesky-app/tag/comatprotorepo/POST/xrpc/com.atproto.repo.putRecord)
823823+///
824824+/// See also: [did.parse](possum/did.html#parse), [nsid.parse](possum/nsid.html#parse), [create_session](#create_session)
813825pub fn put_record(
814826 did: did.Did,
815827 pds host: String,
···861873/// Returns the full blob as originally uploaded.
862874/// Does not require auth; implemented by PDS.
863875///
876876+/// ## Examples
877877+///
878878+/// ```gleam
879879+/// import possum/did
880880+/// import possum
881881+///
882882+/// let assert Ok(did) = did.parse("did:plc:k5vecqzf4d5mdvkcu3mx6l5g")
883883+///
884884+/// let request = possum.get_blog(did, "wibble-wobble", pds: "personal.data-server.pds")
885885+/// ```
886886+///
864887/// Endpoint Docs: [/xrpc/com.atproto.sync.getBlob](https://endpoints.bsky.app/#bluesky-app/tag/comatprotosync/GET/xrpc/com.atproto.sync.getBlob)
888888+///
889889+/// See also: [did](possum/did.html#parse)
865890pub fn get_blob(
866891 did: did.Did,
867867- cid: String,
892892+ cid cid: String,
868893 pds host: String,
869894) -> request.Request(BitArray) {
870895 let query = [#("did", did.to_string(did)), #("cid", cid)]
+12
src/possum/at_uri.gleam
···4040}
41414242/// A URI scheme for addressing atproto repository data.
4343+///
4444+/// See also: [parse](#parse)
4345pub opaque type AtUri {
4446 AtUri(
4547 /// Identifier, can be a DID or a Handle
···6365///
6466/// assert at_uri.authority(at_uri) == "did:plc:vwzwgnygau7ed7b7wt5ux7y2"
6567/// ```
6868+///
6969+/// See also: [Aturi](#AtUri)
6670pub fn authority(self: AtUri) -> Authority {
6771 self.authority
6872}
···7983///
8084/// assert at_uri.collection(at_uri) == "app.bsky.feed.post"
8185/// ```
8686+///
8787+/// See also: [Aturi](#AtUri)
8288pub fn collection(self: AtUri) -> String {
8389 self.collection
8490}
···95101///
96102/// assert at_uri.rkey(at_uri) == "3k5nobkf2w72g"
97103/// ```
104104+///
105105+/// See also: [Aturi](#AtUri)
98106pub fn rkey(self: AtUri) -> String {
99107 self.rkey
100108}
···112120/// let string = "at://did:plc:vwzwgnygau7ed7b7wt5ux7y2/app.bsky.feed.post/3k5nobkf2w72g"
113121/// let assert Ok(at_uri) = at_uri.parse(string)
114122/// ```
123123+///
124124+/// See also: [Aturi](#AtUri)
115125pub fn parse(content: String) -> Result(AtUri, ParseError) {
116126 use value <- result.try(case content {
117127 "at://" <> rest -> Ok(rest)
···183193/// let assert Ok(at_uri) = at_uri.parse(string)
184194/// assert at_uri.to_string(at_uri) == string
185195/// ```
196196+///
197197+/// See also: [Aturi](#AtUri)
186198pub fn to_string(self: AtUri) -> String {
187199 let host = case self.authority {
188200 Handle(value:) -> handle.to_string(value)
+15-3
src/possum/did.gleam
···3030/// identifiers. An example DID is `did:plc:ewvi7nxzyoun6zhxrhs64oiz`.
3131///
3232/// Documentation: [Decentralized Identifiers](https://atproto.com/specs/did)
3333+///
3434+/// See also: [parse](#parse)
3335pub opaque type Did {
3436 Did(method: Method, identifier: String)
3537}
···3941/// ## Examples
4042///
4143/// ```gleam
4444+/// import possum/did
4545+///
4246/// let assert Ok(did) = did.parse("did:plc:k5vecqzf4d5mdvkcu3mx6l5g")
4343-/// let method = possum.method(did)
4747+/// let method = did.method(did)
4448///
4549/// assert method == did.Plc
4650/// ```
5151+///
5252+/// See also: [Did](#Did)
4753pub fn method(self: Did) -> Method {
4854 self.method
4955}
···6369///
6470/// assert identifier == "k5vecqzf4d5mdvkcu3mx6l5g"
6571/// ```
7272+///
7373+/// See also: [Did](#Did)
6674pub fn indentifer(self: Did) -> String {
6775 self.identifier
6876}
69777070-/// Convert a DID to a string.
7878+/// Convert a [DID](#Did) to a string.
7179///
7280/// ## Examples
7381///
···7987///
8088/// assert string == "did:plc:k5vecqzf4d5mdvkcu3mx6l5g"
8189/// ```
9090+///
9191+/// See also: [Did](#Did)
8292pub fn to_string(self: Did) -> String {
8393 case self.method {
8494 Plc -> "did:plc:" <> self.identifier
···117127 Web
118128}
119129120120-/// Parse a string into a valid `Did` type
130130+/// Parse a string into a valid [Did](#Did) type
121131/// If the value is not a valid string then an error is returned.
122132///
123133/// ## Examples
···128138/// let string = "did:plc:k5vecqzf4d5mdvkcu3mx6l5g"
129139/// let assert Ok(did) = did.parse(string)
130140/// ```
141141+///
142142+/// See also: [Did](#Did)
131143pub fn parse(content: String) -> Result(Did, ParseError) {
132144 use with <- result.try(
133145 regexp.from_string(pattern)
+12
src/possum/nsid.gleam
···55//// in reverse domain-name order, followed by an additional name segment.
66//// The hostname part is the **domain authority**, and the final segment is the **name**.
77////
88+//// ## Lexicon
99+////
1010+//// Lexicon is a schema language. It's used in the Atmosphere to describe data
1111+//// records and HTTP APIs. Functionally it's very similar to JSON-Schema and OpenAPI.
1212+//// Lexicon's sole purpose is to help developers build compatible software.
1313+////
814//// Documentation: [Namespaced Identifiers](https://atproto.com/specs/nsid)
9151016import gleam/regexp
···2127}
22282329/// A specification for global semantic IDs.
3030+///
3131+/// See also: [parse](#parse)
2432pub opaque type Nsid {
2533 Nsid(value: String)
2634}
···3745/// let assert Ok(nsid) = nsid.parse(string)
3846/// assert nsid.to_string(nsid) == string
3947/// ```
4848+///
4949+/// See also: [Nsid](#Nsid)
4050pub fn to_string(nsid: Nsid) -> String {
4151 nsid.value
4252}
···5262/// let string = "com.atproto.sync.getRecord."
5363/// let assert Ok(nsid) = nsid.parse(string)
5464/// ```
6565+///
6666+/// See also: [Nsid](#Nsid)
5567pub fn parse(content: String) -> Result(Nsid, ParseError) {
5668 use with <- result.try(
5769 regexp.from_string(pattern)