TypeSafeAPI.Keys (TypeSafe AI v0.1.0-alpha.3)

Copy Markdown View Source

Request-side registry of caller-supplied keys, so answers come back under the keys you sent.

JSON object keys are strings. Elixir callers usually prefer atoms (dept: TypeSafeAPI.choice(...), billing: "..."). Converting response strings back with String.to_atom/1 would let a hostile or buggy response grow the atom table, so this library never does that. Instead it records every question id and Choice option key as given before the request goes out, and looks the wire strings up in that record when decoding.

Keys that were atoms come back as atoms. Keys that were strings come back as strings. A wire key this registry has never seen comes back as the string the API sent.

Summary

Types

A caller-supplied key: an atom or a string.

t()

Functions

Records the question ids and Choice option keys of a normalized question list.

Reads key (an atom) from a map that a caller may have keyed with atoms or strings. Returns nil for anything that is not a map.

Restores the caller's question id for a wire id. Unknown ids are returned as the wire string.

Restores the caller's Choice option key for a wire option under a wire question id. Unknown options are returned as the wire string.

Converts a caller key to its wire form. Atoms become strings; strings pass through. Anything else is an ArgumentError, since the API needs a string.

Types

key()

@type key() :: atom() | String.t()

A caller-supplied key: an atom or a string.

t()

@type t() :: %TypeSafeAPI.Keys{
  ids: %{required(String.t()) => key()},
  options: %{required(String.t()) => %{required(String.t()) => key()}}
}

Functions

build(questions)

@spec build([{key(), TypeSafeAPI.Question.t()}]) :: t()

Records the question ids and Choice option keys of a normalized question list.

Takes [{id, question_struct}] where id is an atom or string.

get(map, key)

@spec get(term(), atom()) :: term()

Reads key (an atom) from a map that a caller may have keyed with atoms or strings. Returns nil for anything that is not a map.

The atom key wins when both are present. A key whose value is false or nil is still a key that is present, so it is returned as-is rather than falling through to the string key.

id(keys, wire_id)

@spec id(t(), String.t()) :: key()

Restores the caller's question id for a wire id. Unknown ids are returned as the wire string.

option(keys, wire_id, wire_option)

@spec option(t(), String.t(), String.t()) :: key()

Restores the caller's Choice option key for a wire option under a wire question id. Unknown options are returned as the wire string.

wire(key)

@spec wire(key()) :: String.t()

Converts a caller key to its wire form. Atoms become strings; strings pass through. Anything else is an ArgumentError, since the API needs a string.