Atex.NSID (atex v0.9.1)

View Source

Represents an AT Protocol Namespaced Identifier (NSID).

An NSID consists of a domain authority (reversed domain name, e.g. "app.bsky.feed") and a name segment (e.g. "post"), optionally followed by a fragment (e.g. "view"), which is a Lexicon-level concept.

Structure

  • authority - the reversed-domain portion, e.g. "app.bsky.feed"
  • name - the final camelCase segment, e.g. "post"
  • fragment - optional fragment string, e.g. "view" (nil for plain NSIDs)

Construction

iex> Atex.NSID.new("app.bsky.feed.post")
{:ok, ~NSID"app.bsky.feed.post"}

iex> Atex.NSID.new("app.bsky.feed.post#view")
{:ok, ~NSID"app.bsky.feed.post#view"}

iex> Atex.NSID.new("invalid")
{:error, :invalid_nsid}

iex> Atex.NSID.new!("app.bsky.feed.post")
~NSID"app.bsky.feed.post"

Sigil

Use ~NSID"..." for convenient literal construction. Raises ArgumentError at the call site if the string is not a valid NSID.

import Atex.NSID, only: [sigil_NSID: 2]
nsid = ~NSID"com.atproto.sync.getRecord"

Summary

Functions

Returns the DNS authority domain for this NSID, as used for lexicon resolution via DNS TXT records.

Returns the canonical Lexicon name for this NSID.

Expands a possible fragment shorthand relative to this NSID.

Returns true if the given string is a syntactically valid NSID (without fragment), false otherwise.

Parses a string into an %Atex.NSID{} struct.

Parses a string into an %Atex.NSID{} struct, raising ArgumentError on invalid input.

Returns the compiled NSID validation regex.

Sigil for constructing an %Atex.NSID{} at runtime, raising ArgumentError for invalid input.

Converts an %Atex.NSID{} to an Elixir module atom.

Converts an %Atex.NSID{} to a {module_atom, fragment_atom} pair.

Converts an %Atex.NSID{} to its canonical string representation.

Types

t()

@type t() :: %Atex.NSID{
  authority: String.t(),
  fragment: (String.t() | nil) | nil,
  name: String.t()
}

Functions

authority_domain(nsid)

@spec authority_domain(t()) :: String.t()

Returns the DNS authority domain for this NSID, as used for lexicon resolution via DNS TXT records.

The authority domain is derived by reversing the authority segments and prepending _lexicon..

Examples

iex> Atex.NSID.authority_domain(~NSID"app.bsky.feed.post")
"_lexicon.feed.bsky.app"

iex> Atex.NSID.authority_domain(~NSID"edu.university.dept.lab.blogging.getBlogPost")
"_lexicon.blogging.lab.dept.university.edu"

canonical_name(nsid)

@spec canonical_name(t()) :: String.t()

Returns the canonical Lexicon name for this NSID.

Returns the plain NSID string when the fragment is "main" or nil, and "nsid#fragment" otherwise.

Examples

iex> Atex.NSID.canonical_name(~NSID"app.bsky.feed.post")
"app.bsky.feed.post"

iex> Atex.NSID.canonical_name(~NSID"app.bsky.feed.post#view")
"app.bsky.feed.post#view"

iex> Atex.NSID.canonical_name(%Atex.NSID{authority: "app.bsky.feed", name: "post", fragment: "main"})
"app.bsky.feed.post"

expand_fragment_shorthand(nsid, ref)

@spec expand_fragment_shorthand(t(), String.t()) :: String.t()

Expands a possible fragment shorthand relative to this NSID.

If ref starts with "#", it is treated as a fragment shorthand and prefixed with the base NSID string. Otherwise ref is returned unchanged.

Examples

iex> Atex.NSID.expand_fragment_shorthand(~NSID"app.bsky.feed.post", "#view")
"app.bsky.feed.post#view"

iex> Atex.NSID.expand_fragment_shorthand(~NSID"app.bsky.feed.post", "com.example.other")
"com.example.other"

match?(value)

@spec match?(String.t()) :: boolean()

Returns true if the given string is a syntactically valid NSID (without fragment), false otherwise.

Examples

iex> Atex.NSID.match?("app.bsky.feed.post")
true

iex> Atex.NSID.match?("invalid")
false

new(string)

@spec new(String.t()) :: {:ok, t()} | {:error, :invalid_nsid}

Parses a string into an %Atex.NSID{} struct.

Accepts an optional #fragment suffix. Returns {:error, :invalid_nsid} if the base NSID portion is not syntactically valid.

Examples

iex> Atex.NSID.new("app.bsky.feed.post")
{:ok, ~NSID"app.bsky.feed.post"}

iex> Atex.NSID.new("app.bsky.feed.post#view")
{:ok, ~NSID"app.bsky.feed.post#view"}

iex> Atex.NSID.new("invalid")
{:error, :invalid_nsid}

new!(string)

@spec new!(String.t()) :: t()

Parses a string into an %Atex.NSID{} struct, raising ArgumentError on invalid input.

Examples

iex> Atex.NSID.new!("app.bsky.feed.post")
~NSID"app.bsky.feed.post"

iex> Atex.NSID.new!("bad")
** (ArgumentError) invalid NSID: "bad"

re()

@spec re() :: Regex.t()

Returns the compiled NSID validation regex.

Useful for embedding into schema validators.

Examples

iex> Atex.NSID.re()
~r/^[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})?)$/

sigil_NSID(arg, list)

(macro)

Sigil for constructing an %Atex.NSID{} at runtime, raising ArgumentError for invalid input.

Examples

iex> import Atex.NSID, only: [sigil_NSID: 2]
iex> ~NSID"app.bsky.feed.post"
~NSID"app.bsky.feed.post"

to_atom(nsid, fully_qualify \\ true)

@spec to_atom(t(), boolean()) :: atom()

Converts an %Atex.NSID{} to an Elixir module atom.

The fragment is ignored; only the base NSID segments are used.

Examples

iex> Atex.NSID.to_atom(~NSID"app.bsky.feed.post")
App.Bsky.Feed.Post

iex> Atex.NSID.to_atom(~NSID"app.bsky.feed.post", false)
:"Elixir.App.Bsky.Feed.Post"

to_atom_with_fragment(nsid)

@spec to_atom_with_fragment(t()) :: {atom(), atom()}

Converts an %Atex.NSID{} to a {module_atom, fragment_atom} pair.

The fragment defaults to :main when absent.

Examples

iex> Atex.NSID.to_atom_with_fragment(~NSID"app.bsky.feed.post")
{App.Bsky.Feed.Post, :main}

iex> Atex.NSID.to_atom_with_fragment(~NSID"app.bsky.feed.post#view")
{App.Bsky.Feed.Post, :view}

to_string(nsid)

@spec to_string(t()) :: String.t()

Converts an %Atex.NSID{} to its canonical string representation.

Includes the fragment if present.

Examples

iex> Atex.NSID.to_string(~NSID"app.bsky.feed.post")
"app.bsky.feed.post"

iex> Atex.NSID.to_string(~NSID"app.bsky.feed.post#view")
"app.bsky.feed.post#view"