1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//! [](https://crates.io/crates/roctokit)
//! [](https://opensource.org/licenses/Apache-2.0)
//! [](https://docs.rs/roctokit/)
//!
//! # Roctokit [core]: Rust Interfaces for a Generated GitHub v3 API
//!
//! **Roctokit** provides high-level client interfaces for interacting with GitHub's v3 API, supporting both synchronous and asynchronous HTTP clients, as well as WebAssembly compatibility.
//!
//! This library extends the `adapter` subsystem, offering flexible and extensible client implementations suitable for production systems. **Roctokit** is designed to be used alongside [roctogen](https://crates.io/crates/roctogen), which generates API models and endpoints from GitHub's OpenAPI specification.
//!
//! ## Getting Started
//!
//! To use **Roctokit**, enable the appropriate feature in your Cargo build command:
//!
//! - Asynchronous requests with `reqwest`: `cargo build --feature reqwest`
//! - Synchronous requests with `ureq`: `cargo build --feature ureq`
//! - WebAssembly support: `cargo build --target wasm32-unknown-unknown`
//!
//! Add both **roctogen** and **roctokit** as dependencies in your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! roctogen = "*"
//! roctokit = "*"
//! ```
//!
//! ### Client Creation
//!
//! GitHub's v3 API supports multiple authentication methods, affecting both access and rate limits. These methods are encapsulated in the [`Auth`](https://docs.rs/roctokit/latest/roctokit/auth/enum.Auth.html) struct, which is passed to the client:
//!
//! - **Basic Authentication**: `Auth::Basic(user, pass)`
//! - **Personal Access Token**: `Auth::Token(token)`
//! - **OAuth Bearer Token**: `Auth::Bearer(bearer)`
//! - **Unauthenticated Access**: `Auth::None`
//!
//! Clients can use either a stock implementation or a custom one that conforms to the [`adapter::Client`](https://docs.rs/roctokit/latest/roctokit/adapters/trait.Client.html) trait. **Roctokit** provides a convenience function to create clients when the appropriate feature is enabled:
//!
//! ```no_compile
//! use roctokit::adapters::client;
//! use roctokit::auth::Auth;
//!
//! let auth = Auth::None;
//!
//! let client = client(&auth).expect("Failed to create client");
//! ```
//!
//! ### APIs and Endpoints
//!
//! The API endpoints are automatically generated by [`roctogen`](https://crates.io/crates/roctogen). For a comprehensive overview of supported endpoints, models, and parameters, consult the [roctogen documentation](https://docs.rs/roctogen/latest/roctogen/).
//!
//! Additional examples on building query parameter structs and making requests are available in the [`roctogen` README](https://github.com/fussybeaver/roctokit/blob/master/roctogen/README.md).
//!
//! ## Custom Client Adapters
//!
//! Beyond the stock implementations, **Roctokit** allows custom client adapters, providing control over pagination, backpressure, and alternative HTTP frameworks. This is an advanced feature best explored through the [examples](https://github.com/fussybeaver/roctokit/tree/master/examples).
//!
//! To create a custom client, implement the [`adapters::Client`](https://docs.rs/roctokit/latest/roctokit/adapters/trait.Client.html) trait:
//!
//! ```no_compile
//! struct MyClient;
//!
//! impl roctokit::adapters::Client for MyClient {
//! type Req = MyRequest;
//! type Err = MyError;
//! type Body = Vec<u8>;
//!
//! // Implement required methods...
//! }
//! ```
//!
//! A custom client integrates with `roctogen` by handling authentication, request building, HTTP transport, and response parsing:
//!
//! - **`type Req`**: Represents a request compatible with the chosen HTTP client.
//! - **`type Err`**: Defines an error type convertible to `roctokit::adapters::AdapterError`.
//! - **`type Body`**: Specifies the request payload type (e.g., JSON body).
//!
//! The following methods must be implemented:
//!
//! - **`new`**: Creates the client instance.
//! - **`build`**: Constructs a `type Req` from a [`GitHubRequest`](https://docs.rs/roctokit/latest/roctokit/adapters/struct.GitHubRequest.html).
//! - **`fetch` / `fetch_async`**: Sends the request synchronously or asynchronously.
//! - **`from_json`**: Serialises a `roctogen` model into a request body.
//!
//! Additionally, the [`GitHubResponseExt`](https://docs.rs/roctokit/latest/roctokit/adapters/trait.GitHubResponseExt.html) trait must be implemented for the response type used by the HTTP client. It includes:
//!
//! - **`is_success`**: Determines whether the response is successful.
//! - **`status_code`**: Retrieves the response status code.
//! - **`to_json` / `to_json_async`**: Parses the response body into a `roctogen` model.
//!
//! ## Testing
//!
//! By default, tests make real HTTP requests to the GitHub API. Some tests use a mock server when the `mock` feature is enabled. The wasm tests require [wasm-pack](https://github.com/rustwasm/wasm-pack) to run.
//!
//! ### WebAssembly Tests
//!
//! ```sh
//! wasm-pack test --firefox --headless
//! ```
//!
//! ### Synchronous Tests
//!
//! ```sh
//! cargo test --target x86_64-unknown-linux-gnu -- --nocapture
//! ```
//!
//! To avoid hitting [GitHub’s API rate limits](https://docs.github.com/en/rest/rate-limit/rate-limit), you can run a local [WireMock](https://www.npmjs.com/package/wiremock) server:
//!
//! ```sh
//! docker run -d --name wiremock -p 8080:8080 -v $PWD/tests/stubs:/home/wiremock rodolpheche/wiremock
//! cargo test --features mock,ureq
//! ```
//!
//! ### Regenerating WireMock Stubs
//!
//! If GitHub's API changes, regenerate the WireMock stubs:
//!
//! ```sh
//! docker run -d --name wiremock -p 8080:8080 -v $PWD/tests/stubs:/home/wiremock -u $(id -u):$(id -g) \
//! rodolpheche/wiremock --verbose --proxy-all="https://api.github.com" --record-mappings
//! ```
//!
//! ## License
//!
//! This project is licensed under the Apache 2.0 License.
use HashMap;