Resourceful.Registry (Resourceful v0.1.6)

View Source

Summary

Functions

Instances of Resourceful.Type are intended to be used in conjunction with a registry in most circumstances. The application, and even the client, will likely understand a resource type by its string name/identifier. Types themselves, when associated with a registry, will be able to reference each other as well, which forms the basis for relationships.

Builds a field graph for a Resourceful.Type. Since types have a max_depth, all possible graphed fields can be computed and cached at compile time when using a registry. This allows nested fields to be treated like local fields in the sense that they are available in a flat map.

A name can be optionally passed to the type/2 macro. If provided, this name will override the name of the resource created in provided block.

Assigns the resource specified in the block and makes it part of the registry. If name is provided, it will rename the resource and use that name as the key.

Ensures a value is a Resourceful.Type and that no type of the same name exists in the map. Raises an exception if both conditions are not met.

Functions

__using__(_)

(macro)

Instances of Resourceful.Type are intended to be used in conjunction with a registry in most circumstances. The application, and even the client, will likely understand a resource type by its string name/identifier. Types themselves, when associated with a registry, will be able to reference each other as well, which forms the basis for relationships.

A module using the Registry behaviour becomes a key/value store. defresourcefultype/1 allows the types to be evaluated entirely at compile time.

build_field_graph(types_map, type_name)

@spec build_field_graph(
  %{
    required(String.t()) => %Resourceful.Type{
      cache: term(),
      fields: term(),
      id: term(),
      max_depth: term(),
      max_filters: term(),
      max_sorters: term(),
      meta: term(),
      name: term(),
      registry: term()
    }
  },
  String.t()
) :: Resourceful.Type.field_graph()

Builds a field graph for a Resourceful.Type. Since types have a max_depth, all possible graphed fields can be computed and cached at compile time when using a registry. This allows nested fields to be treated like local fields in the sense that they are available in a flat map.

For example, a song type would have a title field. Once graphed, it would also have an album.title field. If the depth was set to 2, access to a field like album.artist.name would also be available.

This prevents a lot of recursion logic from being applied at every lookup and by instecting the field graph for a type it's easy to see all of the possible mappings.

Graphed fields are wrapped in a Resourceful.Type.GraphedField struct which contains relational information about the field in addition to the field data itself.

See Resourceful.Type.max_depth/2 for information about what is intended to be included in a field graph based on the depth setting.

do_build_field_graph(field_graph, types_map, type, depth, parent, name_prefix, map_to_prefix)

fetch(rtypes, name)

@spec fetch(map(), String.t()) ::
  {:ok,
   %Resourceful.Type{
     cache: term(),
     fields: term(),
     id: term(),
     max_depth: term(),
     max_filters: term(),
     max_sorters: term(),
     meta: term(),
     name: term(),
     registry: term()
   }}
  | Resourceful.Error.contextual()

fetch!(rtypes, name)

@spec fetch!(map(), String.t()) :: %Resourceful.Type{
  cache: term(),
  fields: term(),
  id: term(),
  max_depth: term(),
  max_filters: term(),
  max_sorters: term(),
  meta: term(),
  name: term(),
  registry: term()
}

fetch_field_graph(field_graphs, name)

@spec fetch_field_graph(
  map(),
  String.t()
  | %Resourceful.Type{
      cache: term(),
      fields: term(),
      id: term(),
      max_depth: term(),
      max_filters: term(),
      max_sorters: term(),
      meta: term(),
      name: term(),
      registry: term()
    }
) ::
  {:ok,
   %{
     required(String.t()) => %Resourceful.Type.GraphedField{
       field: term(),
       map_to: term(),
       name: term(),
       parent: term(),
       query_alias: term()
     }
   }}
  | Resourceful.Error.contextual()

fetch_field_graph!(field_graphs, name)

@spec fetch_field_graph!(
  map(),
  String.t()
  | %Resourceful.Type{
      cache: term(),
      fields: term(),
      id: term(),
      max_depth: term(),
      max_filters: term(),
      max_sorters: term(),
      meta: term(),
      name: term(),
      registry: term()
    }
) :: %{
  required(String.t()) => %Resourceful.Type.GraphedField{
    field: term(),
    map_to: term(),
    name: term(),
    parent: term(),
    query_alias: term()
  }
}

maybe_put_name(type, name)

@spec maybe_put_name(
  %Resourceful.Type{
    cache: term(),
    fields: term(),
    id: term(),
    max_depth: term(),
    max_filters: term(),
    max_sorters: term(),
    meta: term(),
    name: term(),
    registry: term()
  },
  String.t() | nil
) :: %Resourceful.Type{
  cache: term(),
  fields: term(),
  id: term(),
  max_depth: term(),
  max_filters: term(),
  max_sorters: term(),
  meta: term(),
  name: term(),
  registry: term()
}

A name can be optionally passed to the type/2 macro. If provided, this name will override the name of the resource created in provided block.

type(name \\ nil, list)

(macro)

Assigns the resource specified in the block and makes it part of the registry. If name is provided, it will rename the resource and use that name as the key.

If block does not result in a Resourceful.Type an exception will be raised.

validate_type!(type, types)

@spec validate_type!(any(), %{
  required(String.t()) => %Resourceful.Type{
    cache: term(),
    fields: term(),
    id: term(),
    max_depth: term(),
    max_filters: term(),
    max_sorters: term(),
    meta: term(),
    name: term(),
    registry: term()
  }
}) :: %Resourceful.Type{
  cache: term(),
  fields: term(),
  id: term(),
  max_depth: term(),
  max_filters: term(),
  max_sorters: term(),
  meta: term(),
  name: term(),
  registry: term()
}

Ensures a value is a Resourceful.Type and that no type of the same name exists in the map. Raises an exception if both conditions are not met.