guides/quickstart.md

# Installation & Setup Guide

This guide provides detailed instructions for installing and configuring AshRpc in your Phoenix application.

> ⚠️ **EXPERIMENTAL WARNING**: AshRpc is still in early development and considered highly experimental. Breaking changes may occur frequently without notice. We strongly advise against using this package in production environments until it reaches a stable release (v1.0.0+).

## Prerequisites

Before installing AshRpc, ensure you have:

- **Elixir 1.15+**
- **Phoenix 1.7+**
- **Ash Framework 3.0+** (already configured in your application)
- **PostgreSQL** or another supported database

## Installation Options

### Option 1: Automated Installation (Recommended)

The easiest way to get started is using the automated installer:

```bash
# Add ash_rpc to your dependencies using Igniter (if installed)
mix igniter.install ash_rpc

# Or manually add to your mix.exs:
# {:ash_rpc, "~> 0.1"}

# Install dependencies
mix deps.get

# Run the installer
mix ash_rpc.install
```

The installer will:

- ✅ Generate `MyAppWeb.TrpcRouter` module
- ✅ Add tRPC pipeline to your Phoenix router
- ✅ Configure route forwarding to `/trpc`
- ✅ Format generated files

### Option 2: Manual Installation

For more control over the installation process:

#### Step 1: Add Dependencies

Add AshRpc to your `mix.exs`:

```elixir
defp deps do
  [
    ...,
    {:ash_rpc, "~> 0.1"},
  ]
end
```

#### Step 2: Install Dependencies

```bash
mix deps.get
```

#### Step 3: Create tRPC Router

Create a new file `lib/my_app_web/trpc_router.ex`:

```elixir
defmodule MyAppWeb.TrpcRouter do
  use AshRpc.Router,
    domains: [MyApp.Accounts, MyApp.Billing],
    # Optional: Custom transformer for input/output processing
    transformer: AshRpc.Output.Transformer.Identity,
    # Optional: Before hooks
    before: [],
    # Optional: After hooks
    after: [],
    # Optional: Context creation function
    create_context: &AshRpc.Web.Controller.default_context/1
end
```

#### Step 4: Configure Phoenix Router

Add the tRPC pipeline and routes to your `lib/my_app_web/router.ex`:

```elixir
defmodule MyAppWeb.Router do
  use MyAppWeb, :router

  # ... existing pipelines

  # tRPC pipeline - JSON only
  pipeline :ash_rpc do
    plug :accepts, ["json"]
    # Add authentication plugs here if needed
    # plug :retrieve_from_bearer
    # plug :set_actor, :user
  end

  # ... existing routes

  # Mount tRPC under the :trpc pipeline
  scope "/trpc" do
    pipe_through :ash_rpc
    forward "/", MyAppWeb.TrpcRouter
  end
end
```

## Configuration Options

### Router Options

```elixir
defmodule MyAppWeb.TrpcRouter do
  use AshRpc.Router,
    # Required: Domains to expose
    domains: [MyApp.Accounts, MyApp.Billing, MyApp.Notifications],

    # Optional: Custom input/output transformer
    transformer: MyApp.TrpcTransformer,

    # Optional: Before request hooks
    before: [MyApp.TrpcHooks.Logging, MyApp.TrpcHooks.Metrics],

    # Optional: After request hooks
    after: [MyApp.TrpcHooks.Audit],

    # Optional: Custom context creation function
    create_context: &MyApp.TrpcContext.create/1,

    # Optional: Custom middlewares
    middlewares: [MyApp.TrpcMiddleware.Auth, MyApp.TrpcMiddleware.Cache]
end
```

### Custom Hooks

Create custom hooks for request processing:

```elixir
# lib/my_app/trpc_hooks/logging.ex
defmodule MyApp.TrpcHooks.Logging do
  @behaviour AshRpc.Execution.Middleware

  @impl true
  def before_request(ctx) do
    Logger.info("tRPC request: #{ctx.procedure}")
    ctx
  end

  @impl true
  def after_request(ctx, result) do
    Logger.info("tRPC response: #{ctx.procedure} - #{result.status}")
    result
  end
end
```

### Custom Context

Create custom context for requests:

```elixir
# lib/my_app/trpc_context.ex
defmodule MyApp.TrpcContext do
  def create(%Plug.Conn{} = conn) do
    %{
      actor: conn.assigns[:current_user],
      tenant: conn.assigns[:current_tenant],
      request_id: Logger.metadata()[:request_id],
      user_agent: get_user_agent(conn),
      ip_address: get_ip_address(conn)
    }
  end

  defp get_user_agent(conn) do
    conn
    |> Plug.Conn.get_req_header("user-agent")
    |> List.first()
  end

  defp get_ip_address(conn) do
    conn.remote_ip
    |> :inet.ntoa()
    |> to_string()
  end
end
```

## Resource Configuration

### Basic Resource Setup

Configure your Ash resources to expose actions via tRPC:

```elixir
defmodule MyApp.Accounts.User do
  use Ash.Resource,
    extensions: [AshRpc],
    domain: MyApp.Accounts

  # ... resource attributes, actions, etc.

  ash_rpc do
    # Optional: Expose actions (only needed if not using query/mutation entities below)
    # expose [:read, :create, :update, :destroy]

    # Configure specific procedures with advanced features
    query :read do
      filterable true
      sortable true
      selectable true
      paginatable true
    end

    mutation :create
    mutation :update
    mutation :destroy

    # Custom resource name (defaults to module name)
    resource_name "user"

    # Configure method overrides
    methods: [read: :query, create: :mutation]
  end
end
```

### Advanced Query Configuration

```elixir
ash_rpc do
  expose [:read, :create, :search]

  # Configure read queries
  query :read do
    filterable true      # Allow client-side filtering
    sortable true        # Allow client-side sorting
    selectable true      # Allow client-side field selection
    paginatable true     # Allow client-side pagination
    relationships [:posts, :comments, :profile]
  end

  # Custom query for specific use case
  query :search, :read do
    filterable true
    selectable false  # Disable field selection for search
    relationships []  # No relationships for search
  end

  # Configure mutations
  mutation :create, :create do
    metadata fn _subject, user, _ctx ->
      %{user_id: user.id, created_at: user.inserted_at}
    end
  end

  mutation :register, :register_with_password do
    metadata fn _subject, user, _ctx ->
      %{token: user.__metadata__.token, user_id: user.id}
    end
  end
end
```

## Testing the Installation

### 1. Verify Router Setup

Start your Phoenix server:

```bash
mix phx.server
```

### 2. Test Health Check

Make a simple HTTP request to verify the router is working:

```bash
curl -X POST http://localhost:4000/trpc \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"query","params":{}}'
```

You should receive a tRPC-compatible response.

### 3. Configure Resources

Add tRPC configuration to at least one resource:

```elixir
defmodule MyApp.Accounts.User do
  use Ash.Resource, extensions: [AshRpc]

  ash_rpc do
    expose [:read]
  end

  # ... rest of resource
end
```

### 4. Test Resource Endpoint

```bash
curl -X POST http://localhost:4000/trpc/accounts.user.read \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"query","params":{}}'
```

## Troubleshooting

### Common Issues

#### 1. Router Not Found Error

**Error**: `UndefinedFunctionError: function MyAppWeb.TrpcRouter.init/1 is undefined`

**Solution**: Ensure the router module is properly defined and compiled:

```bash
mix compile
mix phx.server
```

#### 2. Domain Not Found Error

**Error**: `Ash.Error.Invalid: Domain MyApp.Accounts not found`

**Solution**: Verify the domain is correctly configured in your router:

```elixir
# Check domain exists
MyApp.Accounts

# Verify router configuration
defmodule MyAppWeb.TrpcRouter do
  use AshRpc.Router, domains: [MyApp.Accounts]  # Correct module name
end
```

#### 3. Resource Not Exposed Error

**Error**: `AshRpc.Error: Resource MyApp.Accounts.User not exposed`

**Solution**: Add tRPC configuration to your resource:

```elixir
defmodule MyApp.Accounts.User do
  use Ash.Resource, extensions: [AshRpc]

  ash_rpc do
    expose [:read]  # Add this block
  end
end
```

#### 4. Authentication Issues

**Error**: `Ash.Error.Forbidden: Access denied`

**Solution**: Configure authentication in your router pipeline:

```elixir
pipeline :ash_rpc do
  plug :accepts, ["json"]
  plug :retrieve_from_bearer  # Add this
  plug :set_actor, :user      # Add this
end
```

### Debug Mode

Enable detailed logging for troubleshooting:

```elixir
# config/dev.exs
config :logger, level: :debug

config :ash_rpc, debug: true
```

## Next Steps

Once installation is complete:

1. **Generate TypeScript Types**:

   ```bash
   mix ash_rpc.codegen --output=./frontend/generated --zod
   ```

2. **Set Up Authentication** (see [Authentication Guide](authentication.md))

## Support

If you encounter issues during installation:

- Check the [troubleshooting section](#troubleshooting) above
- Open an issue on [GitHub](https://github.com/antdragon-os/ash_rpc/issues)
- Join the discussion on [GitHub Discussions](https://github.com/antdragon-os/ash_rpc/discussions)