diff --git a/src/possum/at_uri.gleam b/src/possum/at_uri.gleam index d06dfe4..0f0f067 100644 --- a/src/possum/at_uri.gleam +++ b/src/possum/at_uri.gleam @@ -3,6 +3,8 @@ //// //// AT URIs are not content-addressed, so the contents of the record they //// refer to may also change over time. +//// +//// Documentation: [AT URI Scheme](https://atproto.com/specs/at-uri-scheme) import gleam/result import gleam/string @@ -12,6 +14,8 @@ import possum/handle pub type ParseError { /// Only "at://" is supported InvalidScheme(value: String) + /// Scheme is missing from the URI + MissingScheme /// Authority not a valid Handle InvalidHandleAuthority(reason: handle.ParseError) /// Authority not a valid DID @@ -47,17 +51,50 @@ pub opaque type AtUri { ) } -// Return the authority part of the Uri +/// Return the authority part of the Uri +/// +/// ## Examples +/// +/// ```gleam +/// import possum/at_uri +/// +/// let string = "at://did:plc:vwzwgnygau7ed7b7wt5ux7y2/app.bsky.feed.post/3k5nobkf2w72g" +/// let assert Ok(at_uri) = at_uri.parse(string) +/// +/// assert at_uri.authority(at_uri) == "did:plc:vwzwgnygau7ed7b7wt5ux7y2" +/// ``` pub fn authority(self: AtUri) -> Authority { self.authority } -// Return the collecion part of the Uri +/// Return the collecion part of the Uri +/// +/// ## Examples +/// +/// ```gleam +/// import possum/at_uri +/// +/// let string = "at://did:plc:vwzwgnygau7ed7b7wt5ux7y2/app.bsky.feed.post/3k5nobkf2w72g" +/// let assert Ok(at_uri) = at_uri.parse(string) +/// +/// assert at_uri.collection(at_uri) == "app.bsky.feed.post" +/// ``` pub fn collection(self: AtUri) -> String { self.collection } -// Return the rkey part of the Uri +/// Return the rkey part of the Uri +/// +/// ## Examples +/// +/// ```gleam +/// import possum/at_uri +/// +/// let string = "at://did:plc:vwzwgnygau7ed7b7wt5ux7y2/app.bsky.feed.post/3k5nobkf2w72g" +/// let assert Ok(at_uri) = at_uri.parse(string) +/// +/// assert at_uri.rkey(at_uri) == "3k5nobkf2w72g" +/// ``` pub fn rkey(self: AtUri) -> String { self.rkey } @@ -74,6 +111,7 @@ pub fn rkey(self: AtUri) -> String { /// /// let string = "at://did:plc:vwzwgnygau7ed7b7wt5ux7y2/app.bsky.feed.post/3k5nobkf2w72g" /// let assert Ok(at_uri) = at_uri.parse(string) +/// ``` pub fn parse(content: String) -> Result(AtUri, ParseError) { use value <- result.try(case content { "at://" <> rest -> Ok(rest) @@ -82,7 +120,7 @@ pub fn parse(content: String) -> Result(AtUri, ParseError) { _ -> case string.split_once(content, on: "://") { Ok(scheme) -> Error(InvalidScheme(value: scheme.0)) - Error(_) -> Error(InvalidScheme(value: "")) + Error(_) -> Error(MissingScheme) } }) @@ -124,7 +162,7 @@ fn parse_authority(string: String) -> Result(Authority, ParseError) { Error(reason) -> Error(InvalidDidAuthority(reason:)) } - _handle -> + string -> case handle.parse(string) { Ok(value) -> Ok(Handle(value:)) Error(reason) -> Error(InvalidHandleAuthority(reason:)) @@ -143,7 +181,7 @@ fn parse_authority(string: String) -> Result(Authority, ParseError) { /// "at://did:plc:vwzwgnygau7ed7b7wt5ux7y2/app.bsky.feed.post/3k5nobkf2w72g" /// /// let assert Ok(at_uri) = at_uri.parse(string) -/// assert at.to_string(at_uri) == string +/// assert at_uri.to_string(at_uri) == string /// ``` pub fn to_string(self: AtUri) -> String { let host = case self.authority { diff --git a/src/possum/handle.gleam b/src/possum/handle.gleam index aed2a60..16dff33 100644 --- a/src/possum/handle.gleam +++ b/src/possum/handle.gleam @@ -2,6 +2,8 @@ //// but they can be opaque and unfriendly for human use. Handles are mutable //// and human-friendly account usernames, in the form of a DNS hostname. //// For example, "user.example.com". +//// +//// Documentation: [Handle](https://atproto.com/specs/handle) import gleam/list import gleam/regexp @@ -39,12 +41,33 @@ pub opaque type Handle { Handle(value: String) } +/// Convert a handle into a String +/// +/// ## Examples +/// +/// ```gleam +/// import possum/handle +/// +/// let string = "gleam.run" +/// let assert Ok(handle) = handle.parse(string) +/// +/// assert handle.to_string(handle) == "gleam.run" +/// ``` pub fn to_string(handle: Handle) -> String { handle.value } /// Parse a string into a valid `Handle` type /// If the value is not a valid string then an error is returned. +/// +/// ## Examples +/// +/// ```gleam +/// import possum/handle +/// +/// let string = "gleam.run" +/// let assert Ok(handle) = handle.parse(string) +/// ``` pub fn parse(content: String) -> Result(Handle, ParseError) { use with <- result.try( regexp.from_string(pattern) diff --git a/src/possum/nsid.gleam b/src/possum/nsid.gleam index a14c82c..071b930 100644 --- a/src/possum/nsid.gleam +++ b/src/possum/nsid.gleam @@ -4,10 +4,13 @@ //// The basic structure and semantics of an NSID are a fully-qualified hostname //// in reverse domain-name order, followed by an additional name segment. //// The hostname part is the **domain authority**, and the final segment is the **name**. +//// +//// Documentation: [Namespaced Identifiers](https://atproto.com/specs/nsid) import gleam/regexp import gleam/result +/// Available on: https://atproto.com/specs/nsid#nsid-syntax const pattern = "^[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(\\.[a-zA-Z]([a-zA-Z0-9]{0,62})?)$" pub type ParseError { @@ -22,6 +25,18 @@ pub opaque type Nsid { Nsid(value: String) } +/// Convert a NSID into a String +/// +/// ## Examples +/// +/// ```gleam +/// import possum/nsid +/// +/// let string = "com.atproto.sync.getRecord" +/// +/// let assert Ok(nsid) = nsid.parse(string) +/// assert nsid.to_string(nsid) == string +/// ``` pub fn to_string(nsid: Nsid) -> String { nsid.value }