# `MobDev.GooglePlay.CloudSetup`
[🔗](https://github.com/genericjam/mob_dev/blob/master/lib/mob_dev/google_play/cloud_setup.ex#L1)

Google Cloud REST API operations for the Play Store setup wizard.

Covers the three Google Cloud steps that `mix mob.setup.google_play` automates:
- Enabling the Android Publisher API in a Cloud project
- Creating a `play-publisher` service account
- Generating and saving a JSON key for that service account

All functions take an OAuth2 `access_token` obtained from `MobDev.GooglePlay.OAuth`.

## API surface used

| Step | API |
|------|-----|
| List projects | Cloud Resource Manager v3 |
| Enable Android Publisher API | Service Usage v1 |
| Create service account | IAM v1 |
| Create JSON key | IAM v1 |

# `build_enable_api_url`

```elixir
@spec build_enable_api_url(String.t(), String.t()) :: String.t()
```

Builds the Service Usage API URL for enabling a specific service.

Pure function — useful for testing and debugging.

# `create_and_save_key`

```elixir
@spec create_and_save_key(String.t(), String.t(), String.t(), String.t()) ::
  {:ok, Path.t()} | {:error, String.t()}
```

Creates a JSON key for the given service account and saves it to disk.

The key is written to `~/.google_play/{filename}.json` (mode 600).
Returns `{:ok, path}` where `path` is the absolute path to the saved file,
or `{:error, reason}`.

# `create_service_account`

```elixir
@spec create_service_account(String.t(), String.t(), String.t()) ::
  {:ok, String.t()} | {:error, String.t()}
```

Creates the `play-publisher` service account in the given Cloud project.

Returns `{:ok, email}` where `email` is the service account email, or
`{:error, reason}`.

If the service account already exists (HTTP 409), returns its email
without error.

# `enable_publisher_api`

```elixir
@spec enable_publisher_api(String.t(), String.t()) :: :ok | {:error, String.t()}
```

Enables the Android Publisher API in the given Cloud project.

The operation may take up to 60 seconds; this function polls until complete.
Returns `:ok` or `{:error, reason}`.

# `list_projects`

```elixir
@spec list_projects(String.t()) :: {:ok, [map()]} | {:error, String.t()}
```

Lists Google Cloud projects accessible to the authenticated user.

Returns `{:ok, [%{"projectId" => id, "displayName" => name, ...}]}` or
`{:error, reason}`.

# `parse_projects_response`

```elixir
@spec parse_projects_response(map()) :: [map()]
```

Parses the `projects` list from a Cloud Resource Manager response body.

Pure function — used for testing without HTTP calls.

# `save_key_file`

```elixir
@spec save_key_file(String.t(), String.t()) :: {:ok, Path.t()} | {:error, String.t()}
```

Decodes a base64url-encoded service account JSON key and saves it to disk.

The `b64_json` parameter is the `privateKeyData` field from the IAM keys API
response (standard base64, not URL-safe). Saved to `~/.google_play/{filename}.json`
with mode 600.

Pure IO side-effect (no HTTP) — useful for testing.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
