# client elixir (Protobuf)

Source: https://apigenie.pl/techdocs/reference/cli-generate_client_elixir_protobuf

Generate an Elixir gRPC client on [elixir-grpc](https://hexdocs.pm/grpc) from a `.proto` file and
the files it imports.

## Usage

```sh
apigenie-generator client elixir [...OPTIONS] INPUT_FILE.proto
```

## Description

`client elixir` generates a gRPC client when its input is a `.proto` file (an OpenAPI document
gives a Req client, see [client elixir](/techdocs/reference/cli-generate_client_elixir)). The input is the file
declaring the services; the files it imports are looked up in the directories of `--proto-path`,
then next to it, and `google/protobuf`, `google/api` and `google/rpc` imports need no files. Only
proto3 files are read.

The generator writes a Mix project (Elixir 1.18 or later) depending on `grpc` 1.0 with Mint, and
`protobuf` 0.17. Its code passes `mix format --check-formatted`, `mix compile
--warnings-as-errors`, `mix credo --strict` and `mix dialyzer`. No protoc is needed: the modules of
the messages, services and stubs are those protoc-gen-elixir would write, named the same way (see
[server elixir-grpc](/techdocs/reference/cli-generate_server_elixir_grpc)).

| File | Contents |
| ---- | -------- |
| `lib/proto/<path>.pb.ex` | per `.proto` file, a module per message, map entry and enum, and the `<Service>.Service` and `<Service>.Stub` modules of each service |
| `lib/<app>.ex` | the root module: `connect/2`, the types of options and results |
| `lib/<app>/<service>.ex` | a module per service, with a function per method |
| `mix.exs`, `.formatter.exs`, `.gitignore`, `README.md` | the project |

```elixir
{:ok, channel} = CarpetExpressClient.connect("localhost:50051")

{:ok, shipment} =
  CarpetExpressClient.ShipmentService.get_shipment(
    channel,
    %Carpetexpress.V1.GetShipmentRequest{id: "sh_1"},
    timeout: 5_000,
    metadata: %{"x-tenant" => "acme"}
  )
```

### Functions

A method is a function named as GRPC.Stub names it (`GetShipment` is `get_shipment/3`):

| Method | Arguments | Returns |
| ------ | --------- | ------- |
| unary | channel, request, options | `{:ok, response}` or `{:error, %GRPC.RPCError{}}` |
| server streaming | channel, request, options | `{:ok, stream}`: an `Enumerable` of `{:ok, message}` and `{:error, %GRPC.RPCError{}}` items |
| client streaming | channel, `Enumerable` of requests, options | `{:ok, response}` or `{:error, %GRPC.RPCError{}}` |
| bidirectional streaming | channel, `Enumerable` of requests, options | like server streaming; the requests are sent from a task while the responses arrive |

The options are those of GRPC.Stub: `:timeout` (milliseconds; 10 seconds for unary calls) or
`:deadline` (a `DateTime`), `:metadata` (a map of headers) and `:compressor`. `connect/2` passes
its options to `GRPC.Stub.connect/2` with the Mint adapter unless `:adapter` names another one.
The Stub modules remain available for calls the functions don't cover, e.g. interleaving the
requests and responses of a bidirectional stream. Deprecated methods are `@deprecated`.

### Limitations

- `extend` blocks aren't generated; a warning names the file.
- `(google.api.field_behavior) = REQUIRED` isn't checked before sending.

## Options

### -I, --proto-path DIR

Directory searched for the imported files, like protoc's `--proto_path`. Can be repeated. Given
with an OpenAPI input, it is an error.

### -c, --config

Path to the configuration file to use. See the "Configuration" section for more information.

### -o, --output

Directory where the project is generated.

### --package-name

Name of the Mix application, converted to snake_case (`carpet-express-client` gives
`carpet_express_client` and the root module `CarpetExpressClient`). Defaults to the name of the
output directory.

### --package-version

Version of the Mix project; `0.1.0` by default.

### -p, --property NAME=VALUE

Sets a generator option (see below), e.g. `-p package_prefix=acme.proto`. Options given on the
command line take precedence over the configuration file.

## Configuration

The options are in the `protobuf` section of `client_elixir`; the others concern OpenAPI input.

```yaml
version: '1.0'
commands:
  generate:
    client_elixir:
      protobuf:
        app: carpet_express_client
        dev_deps: false
```

| Option | Type | Default | Description |
| ------ | ---- | ------- | ----------- |
| `app` | string | name of the output directory | Name of the Mix application (snake_case, the directory under `lib/`); also set by `--package-name`. |
| `namespace` | string | the application in PascalCase | Root module of the client's modules, e.g. `CarpetExpressClient`. |
| `package_prefix` | string | | Prepended to the package in the names of the modules of messages, enums and services, like protoc-gen-elixir's `package_prefix`. |
| `dev_deps` | boolean | `true` | Lists credo and dialyxir as dependencies of `mix.exs` (`only: :dev`). |
