# BridgeEx

A library to build bridges to other services (actually only graphql ones are supported).

## Usage

### A GraphQL bridge

Define a behaviour with the queries/mutations you're going to need for the bridge:

defmodule MyApp.SomeService do
  @moduledoc """
  Bridge definition for SomeService

  @callback my_cool_query(any()) :: {:ok, map()} | {:error, any()}

Implement the behaviour:

defmodule MyApp.SomeServiceBridge do
  @moduledoc """
  Bridge implementation for SomeService behaviour.

  @behaviour MyApp.SomeService

  use BridgeEx.Graphql, [
    # mandatory settings
    endpoint: "",

    # optional settings (with defaults)
    http_headers: %{
      "User-Agent" => "microservice-myapp/myapp-version",
      "Content-type" => "application/json",
      "X-Client-Id" => "myapp",
      "X-Client-Secret" => "myapp_secret"
    http_options: [timeout: 1_000, recv_timeout: 16_000],
    max_attempts: 1,
    encode_variables: false,
    format_response: true, # formats keys from CamelCase to snake_case
    log_options: [log_query_on_error: true, log_response_on_error: false]

  def my_cool_query(%{} = variables) do
    call("a graphql query or mutation", variables)

    # or, if you need more granularity (ex: different endpoint or options):

    #   "",
    #   "graphql query or mutation",
    #   variables,
    #   encode_variables: false,
    #   [timeout: 1_000, recv_timeout: 16_000],
    #   %{
    #     "Some-Header" => "some-value",
    #   },
    #   1
    # )


You can now use your bridge module:

MyApp.SomeServiceBridge.my_cool_query(%{var: 1})

As a good practice, if you want to mock your bridge for testing, you _should_ implement another module:

defmodule MyApp.SomeServiceBridgeMock do
  @behaviour MyApp.SomeService

  alias BridgeEx.Graphql.Utils

  def my_cool_query(%{} = variables) do!("some_mock_file.json")
    |> Json.decode!(keys: :atoms)
    |> Utils.parse_response() # required to parse data
    # |> BridgeEx.Graphql.Client.format_response() # optional, if you want to format response

You can now set the right module in your `config/*` directory:

config :my_app, :some_service_bridge, MyApp.SomeServiceBridge

# or

config :my_app, :some_service_bridge, MyApp.SomeServiceBridgeMock

And use it in your app from configuration:

@some_service Application.compile_env!(:my_app, :some_service_bridge)

# ...

@some_service.my_cool_query(%{var: 2})

See [example](example) directory for an implementation, it also works in `dev` and `test` environments.

### Authenticating calls via Auth0

`bridge_ex` supports authentication of machine-to-machine calls via Auth0, through the [prima_auth0_ex]( library.

To use this feature, simply configure your bridge with the audience of the target service:

  use BridgeEx.Graphql, [endpoint: "...", auth0: [enabled: true, audience: "target_audience"]]

For this feature to work, your `config.exs` must be updated with the configuration for the `prima_auth0_ex` library.
You can refer to [the library's README]( for more information on the supported configuration.

## Development

`mix deps.get && mix test`

## Installation

The package can be installed by adding `bridge_ex` to your list of dependencies in `mix.exs`:

def deps do
    {:bridge_ex, "~> 0.4.0"}

## Copyright and License

Copyright (c) 2020

This work is free. You can redistribute it and/or modify it under the
terms of the MIT License. See the [](./ file for more details.