Composer.Recipe.Group (composer v0.2.0)

Copy Markdown View Source

A recipe group: one recipes/<group>.exs file holding one or more recipes, keyed by name.

# recipes/ash.exs
[
  base: [
    shortdoc: "Ash core: sourceror, ash and ash_phoenix",
    steps: ["composer_lab:sourceror", "composer_lab:ash", "composer_lab:ash/phoenix"]
  ],
  ecto: [
    shortdoc: "Ash with the Postgres data layer",
    steps: [{:use, "base"}, "composer_lab:ash/postgres"]
  ]
]

The file name is the group name, so ecto above is <cookbook>:ash/ecto. Group and recipe names are lowercase [a-z0-9_] segments.

Reading without evaluating

ids/1 reads the recipe names from the file's syntax tree, without running it, so listing and completion never evaluate a group. That is why the file must end in a literal keyword list ([name: [...], ...]). Bindings before it are fine; the values may be any expression.

The bindings are also how recipes in a group share settings, such as cookbook aliases (see Composer.Recipe):

# recipes/auth.exs
aliases = [lab: "composer_lab"]

[
  passkeys: [
    shortdoc: "Passkey sign-in",
    aliases: aliases,
    steps: ["lab:auth/passkeys"]
  ],
  magic: [
    shortdoc: "Magic-link sign-in",
    aliases: aliases,
    steps: ["lab:auth/magic_link"]
  ]
]

load/2 evaluates the file once and validates every recipe in it (see Composer.Recipe for the keys). A problem with the file as a whole (its shape, a duplicate name) makes every recipe in it unusable; a problem with one recipe only affects that recipe (see load_all/2).

Summary

Functions

Validates an evaluated group term. Returns the valid recipes and every problem found, as error reasons for Composer.Error.message/1.

Like check/3, with each problem as {reason, recipe_ref}: the recipe it was found in, or nil for a problem with the file as a whole.

Returns the names that appear more than once in names.

Like names/1, sorted and without duplicates.

Evaluates and validates the group file at path, in cookbook cookbook, returning its recipes in file order. The first problem found is returned as the error; check/3 returns all of them.

Evaluates the group file at path and returns its valid recipes and the problems of the others. A problem with the file as a whole is an error.

The group name of a group file: its base name without .exs.

Returns the recipe names in a group file, in file order, read from its syntax tree. Duplicates are kept; see duplicates/1.

Like names/1, for a group file's source; path words errors.

Picks recipe name from the result of load_all/2: the recipe, or the first problem found with it.

True for a valid group or recipe name.

Functions

check(term, path, cookbook)

@spec check(term(), Path.t(), String.t()) :: {[Composer.Recipe.t()], [term()]}

Validates an evaluated group term. Returns the valid recipes and every problem found, as error reasons for Composer.Error.message/1.

check_tagged(term, path, cookbook)

@spec check_tagged(term(), Path.t(), String.t()) ::
  {[Composer.Recipe.t()], [{term(), String.t() | nil}]}

Like check/3, with each problem as {reason, recipe_ref}: the recipe it was found in, or nil for a problem with the file as a whole.

duplicates(names)

@spec duplicates([String.t()]) :: [String.t()]

Returns the names that appear more than once in names.

ids(path)

@spec ids(Path.t()) :: {:ok, [String.t()]} | {:error, term()}

Like names/1, sorted and without duplicates.

load(path, cookbook)

@spec load(Path.t(), String.t()) :: {:ok, [Composer.Recipe.t()]} | {:error, term()}

Evaluates and validates the group file at path, in cookbook cookbook, returning its recipes in file order. The first problem found is returned as the error; check/3 returns all of them.

load_all(path, cookbook)

@spec load_all(Path.t(), String.t()) ::
  {:ok, {[Composer.Recipe.t()], [term()]}} | {:error, term()}

Evaluates the group file at path and returns its valid recipes and the problems of the others. A problem with the file as a whole is an error.

name(path)

@spec name(Path.t()) :: String.t()

The group name of a group file: its base name without .exs.

names(path)

@spec names(Path.t()) :: {:ok, [String.t()]} | {:error, term()}

Returns the recipe names in a group file, in file order, read from its syntax tree. Duplicates are kept; see duplicates/1.

names(content, path)

@spec names(String.t(), Path.t()) :: {:ok, [String.t()]} | {:error, term()}

Like names/1, for a group file's source; path words errors.

pick(arg, path, cookbook, name)

@spec pick({[Composer.Recipe.t()], [term()]}, Path.t(), String.t(), String.t()) ::
  {:ok, Composer.Recipe.t()} | {:error, term()}

Picks recipe name from the result of load_all/2: the recipe, or the first problem found with it.

valid_name?(name)

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

True for a valid group or recipe name.