Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,20 @@ Failed responses are mapped in `GithubConnector`:

Pull requests are welcome. Run `composer test` before opening one.

## Patterns and Architecture

### 3-Way CLI Pattern

This package provides three complementary ways to interact with the GitHub API:

| Pattern | Use Case | Example |
|---------|----------|---------|
| **Facade** (`Github::`) | Quick, static access | `Github::repos()->all()` |
| **Resources** (`repos()`) | Organized, grouped methods | `Github::repos()->all()` |
| **CLI** (`php artisan github-client`) | Command-line scripts | `php artisan github-client test` |

The `Github` class is the **core package** that ties all three together. See [docs/3WAY-CLI-PATTERN.md](./docs/3WAY-CLI-PATTERN.md) for details.

## License

MIT. See [LICENSE.md](LICENSE.md).
Expand Down
183 changes: 183 additions & 0 deletions docs/3WAY-CLI-PATTERN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# 3-Way CLI Pattern

This package implements a **3-Way CLI Pattern** that provides three complementary ways to interact with the GitHub API:

```
┌─────────────────────────────────────────────────────────────────────────────┐
│ 3-Way CLI Pattern │
├─────────────────────────────────────────────────────────────────────────────┤
│ 1. Facade (Github::) 2. Resources (repos(), issues()) 3. CLI Command │
│ Static Access Method Grouping Artisan Command │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ Core Package Role │
│ The Github Class │
│ Orchestrates all three access patterns through a single, consistent API │
└─────────────────────────────────────────────────────────────────────────────┘
```

## The Three Ways

### Way 1: Facade Access (`Github::`)

Use the `Github` facade for static, convenient access to the API:

```php
use JordanPartridge\GithubClient\Facades\Github;

// List repositories
$repos = Github::repos()->all()->dto();

// Get a specific repository
$repo = Github::getRepo('laravel/framework');
```

**Use when**: You want the simplest, most direct access to the API without dependency injection.

### Way 2: Resource Methods (`repos()`, `issues()`)

Access the API through resource-specific methods that group related functionality:

```php
use JordanPartridge\GithubClient\Facades\Github;
use JordanPartridge\GithubClient\ValueObjects\Repo;

// Repository resource
$repos = Github::repos()->all()->dto();
$name = Repo::fromFullName('laravel/framework');
$repo = Github::repos()->get($name);
Github::repos()->delete($name);

// Issue resource
$issue = Github::issues()->create($owner, $repo, $title, $body);

// Pull request resource
$pullRequests = Github::pullRequests()->all($owner, $repo);
```

**Use when**: You want organized access to related API endpoints, or when injecting the client for testability.

### Way 3: CLI Command (`php artisan github-client`)

Use Artisan commands for quick inspections and testing from the command line:

```bash
# Test the GitHub API connection
php artisan github-client test

# Show repository information

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example uses undefined $repo on RHS: $repo = Github::repos()->get($repo);. Should be a literal like get('owner/repo') or introduce a prior assignment.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 3819b15: the example now builds a Repo with Repo::fromFullName('laravel/framework') and passes it to get() and delete(). pint, phpstan and pest pass locally.

php artisan github-client repo --repo=laravel/framework

# Show recent commits
php artisan github-client commits --repo=laravel/framework --limit=10
```

**Use when**: You need quick access to GitHub data without writing PHP code, or for debugging.

## The Core Package Role

The `Github` class is the **core package** that ties all three access methods together:

```php
namespace JordanPartridge\GithubClient;

use JordanPartridge\GithubClient\Connectors\GithubConnector;
use JordanPartridge\GithubClient\Resources\RepoResource;
use JordanPartridge\GithubClient\Resources\IssuesResource;
use JordanPartridge\GithubClient\Resources\PullRequestResource;
// ... all other resources

class Github
{
public function __construct(
protected GithubConnector $connector,
) {}

// Resource methods - connect to resources
public function repos(): RepoResource
{
return new RepoResource($this);
}

public function issues(): IssuesResource
{
return new IssuesResource($this);
}

public function pullRequests(): PullRequestResource
{
return new PullRequestResource($this);
}

// ... all other resource methods
}
```

### Core Responsibilities

1. **Resource Factory**: Creates resource instances (`repos()`, `issues()`, etc.)

2. **Connector Holder**: Maintains a single `GithubConnector` instance for HTTP requests

3. **Authentication Gateway**: Routes authentication through `GithubConnector`

4. **Rate Limit Tracking**: Provides rate limit information via `getRateLimitStatus()`

5. **GitHub App Support**: Handles installation-based authentication via `forInstallation()` and `withApp()`

### How the Core Ties Everything Together

```
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Facade │ │ Resources │ │ CLI │
│ Github:: │ │ repos(), │ │ artisan │
│ static calls │────▶│ issues() │────▶│ github-client│
└──────────────┘ │ pullRequests()│ └──────────────┘
└──────────────┘
│
▼
┌──────────────┐
│ Core │
│ Github │
│ class │
└──────────────┘
│
▼
┌──────────────┐
│ Connector │
│ (HTTP) │
└──────────────┘
│
▼
┌──────────────┐
│ GitHub API │
└──────────────┘
```

## Choosing the Right Pattern

| Scenario | Recommended Pattern |
|----------|---------------------|
| Quick script or quick test |_facade (`Github::`) |
| Class-based architecture |_Inject `Github` class |
| Related endpoint group | Use resource (`repos()`) |
| CI/CD scripts or shell automation | CLI command |
| Debugging | CLI command |

## Example: All Three Ways to List Repositories

```php
// Way 1: Facade
use JordanPartridge\GithubClient\Facades\Github;
$repos = Github::repos()->all()->dto();

// Way 2: Resource
$repos = Github::repos()->all()->dto();

// Way 3: CLI
// php artisan github-client list-repos
```

All three ways use the same underlying core package and return the same results.
10 changes: 10 additions & 0 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

`jordanpartridge/github-client` is a Laravel package for the GitHub REST API. It is built on [Saloon](https://docs.saloon.dev) and returns typed PHP objects instead of raw arrays. It requires PHP 8.2 or newer and Laravel 11, 12, or 13. CI runs the suite on PHP 8.2, 8.3, and 8.4.

## 3-Way CLI Pattern

This package implements a **3-Way CLI Pattern** with three complementary ways to access the GitHub API:

1. **Facade** (`Github::`) - Static access for convenience
2. **Resources** (`repos()`, `issues()`) - Grouped methods by feature area
3. **CLI Command** (`php artisan github-client`) - Command-line interface

The `Github` class is the **core package** that orchestrates all three access patterns. See [docs/3WAY-CLI-PATTERN.md](./3WAY-CLI-PATTERN.md) for a detailed explanation.

## Layers

```
Expand Down
5 changes: 3 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ The [README](../README.md) is the install and usage guide. The pages below cover
1. [Getting started](./getting-started.md)
2. [API reference](./api-reference.md)
3. [Authentication and errors](./advanced-usage.md)
4. [How the client is put together](./core-concepts.md)
5. [Architecture](./ARCHITECTURE.md)
4. [3-Way CLI Pattern](./3WAY-CLI-PATTERN.md)
5. [How the client is put together](./core-concepts.md)
6. [Architecture](./ARCHITECTURE.md)
20 changes: 20 additions & 0 deletions docs/core-concepts.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# How the client is put together

This package implements a **3-Way CLI Pattern** that provides three complementary ways to interact with the GitHub API:

1. **Facade** (`Github::`) - Static access for convenience
2. **Resources** (`repos()`, `issues()`) - Grouped methods by feature area
3. **CLI Command** (`php artisan github-client`) - Command-line interface

The `Github` class is the **core package** that orchestrates all three access patterns. See [3-Way CLI Pattern](./3WAY-CLI-PATTERN.md) for a detailed explanation.

`GithubClientServiceProvider` registers four things:

- The `github-client` config file
Expand All @@ -14,3 +22,15 @@ DTOs in `src/Data` are plain PHP objects with a `fromArray()` or `fromApiRespons
`Repo::fromFullName('owner/repo')` checks that the string has one slash and that each side matches `[a-zA-Z0-9._-]+`.

Enums replace a few query strings: `Visibility`, `Sort`, `Direction`, `Repos\Type`, `Issues\State`, `Issues\Sort`, `Pulls\State`, `Pulls\Sort`, and `MergeMethod`. Pull request list filters are still a plain array.

## The Core Package Role

The `Github` class is the **core package** that ties all three access patterns together:

- **Resource Factory**: Creates resource instances (`repos()`, `issues()`, etc.)
- **Connector Holder**: Maintains a single `GithubConnector` for HTTP requests
- **Authentication Gateway**: Routes all authentication through `GithubConnector`
- **Rate Limit Tracking**: Provides rate limit info via `getRateLimitStatus()`
- **GitHub App Support**: Handles installation-based auth via `forInstallation()` and `withApp()`

All three ways to access the API (Facade, Resources, CLI) use the same `Github` core class.
Loading