README.md

# Valspec

**A simple elixir library for Phoenix that combines Swagger documentation and parameter validation**

## Installation

The latest version of Valspec is built on top [open_api_spex](https://github.com/open-api-spex/open_api_spex). You will need to install it along with the Valspec dependency:

```elixir
def deps do
  [
    {:open_api_spex, "~> 3.21"},
    {:valspec, "~> 0.1.0"}
  ]
end
```

## Adding to your project

### Define your spec

The first thing you will need to do is define your `open_api_spex` spec definition.
Visit the [Generate Spec](https://github.com/open-api-spex/open_api_spex?tab=readme-ov-file#generate-spec) section in the github repo for more information.

### Serving your spec (Running Swagger UI)
Visit the [Serve Spec](https://github.com/open-api-spex/open_api_spex?tab=readme-ov-file#serve-the-spec) section in the github repo for more information on how to run the UI.

### Add Valspec to your controller
```elixir
  defmodule MyAppWeb.ExampleUsersController do
    use Valspec

    valspec_create :create_user, summary: "Creates a User" do
      required(:first_name, :string, example: "Greg")
      required(:role, :enum, values: [:admin, :normal], default: :normal)
      optional(:last_name, :string, example: "Jones")
      optional(:age, :integer, minimum: 18)
    end

    def create(conn, params) do
      with {:ok, user_params} <- valspec_validate(:create_user, params) do
        ...
      end
    end
  end
```

### Creating a schema
Using `valspex_schema/0` allows you to define response or callback schemas for your documentation. `valspex_schema/0` uses Ecto `embedded_schema` under the hood and uses its
syntax:

```elixir
  defmodule MyAppWeb.Users.Schema do
    use Valspec

    valspec_schema do
      field :id, :uuid, example: "82b557d1-0000-0000-0000-55df16add1b5"
      field :first_name, :string, example: "Greg"
      field :last_name, :string, example: "Jones"
      field :role, :enum, values: [:admin, :normal]
      field :age, :integer
    end
  end

  # You can use a valspec schema within other valspec schemas via `embeds_one/2` or `embeds_many/2`
  defmodule MyApp.Users.SucessResponse do
    use Valspec

    valspec_schema do
      embeds_one :data, MyAppWeb.Users.Schema
    end
  end
```

You can use the schema by using the `default_response_schema` opt on init or by passing the `response_schema` to the valspec operation:

```elixir
  defmodule MyAppWeb.ExampleUsersController do
    use Valspec,
    # Applies to all actions unless overridden
    default_response_schema: MyApp.Users.SucessResponse
    
    # Uses MyApp.Users.SucessResponse
    valspec_create :create_user, summary: "Creates a User" do
      required(:first_name, :string, example: "Greg", nullable: true)
    end

    valspec_update 
      :update_user, 
      summary: "Updates a User"
      # Overrides default MyApp.Users.SucessResponse
      response_schema: MyApp.Users.UpdateSucessResponse do
      required(:first_name, :string, example: "Greg")
    end
  end
```


### Using schemas for type safety
You can use your schemas directly in your responses to ensure your documentation is always up-to-date like so:

```elixir
defmodule MyAppWeb.ExampleUsers.JSON do 
  def create(%{user: user}) do
    %MyApp.Users.SucessResponse{data: data(user)}
  end

  defp data(%User{} = user) do
    %MyAppWeb.Users.Schema{
      id: user.id,
      first_name: user.first_name,
      last_name: user.last_name,
      role: user.role,
      age: user.age
    }
  end
end
```

## List of operations
  The following macros are exposed:

  * `valspec_create/3`- define specs for a controller's #create/2 action
  * `valspec_update/3`- define specs for a controller's #update/2 action
  * `valspec_index/1` - define specs for a controller's #index/2 action
  * `valspec_delete/1` - define specs for a controller's #delete/2 action
  * `valspec_show/1` - define specs for a controller's #show/2 action
  * `valspec_custom/2` - define specs for a custom controller action.
  * `valspec_custom/4` - define specs for a custom controller action.
  * `valspec_schema/1`- defines a struct that can used in defining responses.

  ## Examples
  There is an example phoenix project in this repo under `/examples/my_app`. You can run the app and navigate to the `/swaggerui#` to see the example