PK     d,]    	  readme.mdnu         # APIZ

APIZ is a PHP API Client Development Kit, it helps you to manage HTTP API call in OOP way. You can easily handle and isolate all kinds of REST API calls and their responses by using this package.

## Requirements

- PHP >= 5.5.9

## Installations

```shell
composer require nahid/apiz
```

## Configurations

There are no extra configurations for this package.

## Usage

Lets see an example to consume API from https://reqres.in.

Suppose you need to create several API services for your project. Your service directory is
`app/Services`. Now we are going to develop a service for https://reqres.in and make a class file `ReqResApiService.php`
which will extend `\Apiz\AbstractApi` class.

```php
namespace App\Services;

use Apiz\AbstractApi;

class ReqResApiService extends AbstractApi
{
    protected function getBaseURL()
    {
        return 'https://reqres.in';
    }
}
```

`getBaseURL()` is an abstract method of the `AbstractApi` class. You need to override this method to set the proper base URL for your API.

Few APIs have a common prefix in their URL. Like, here `reqres.in` have a prefix `api` on every endpoint. 
So, we'll override the `getPrefix()` method to define the Prefix.

```php
namespace App\Services;

use Apiz\AbstractApi;

class ReqResApiService extends AbstractApi
{
    protected function getBaseURL()
    {
        return 'https://reqres.in';
    }

    protected function getPrefix()
    {
        return 'api';
    }
}
```

Now let's make a method to get all users info.

```php
namespace App\Services;

use Apiz\AbstractApi;

class ReqResApiService extends AbstractApi
{
    protected function getBaseURL()
    {
        return 'https://reqres.in';
    }

    protected function getPrefix()
    {
        return 'api';
    }

    public function getAllUsers()
    {
        $response = $this->get('users');

        if ($response->getStatusCode() === 200) {
            return $response()->toArray();
        }

        return [];
    }
}
```
So, we are basically making a `GET` request to the URL `https://reqres.in/api/users`.

See, how easy it is to manage an API now?

Let's see another example.

## Post Request with Form Params

```php
public function createUser(array $data)
{
    $response = $this->withFormParams($data)
            ->post('create');

    if ($response->getStatusCode() === 201) {
        return $response()->toArray();
    }

    return null;
}
```

## Default Headers

Sometimes we need to bind some headers with all the requests. Suppose if you want to deal with the Github API, you have to send `access_token` in every request with the headers.
So APIZ provide you a handy way to deal with this problem. Just override `AbstractApi::getDefaultHeaders()`.


```php
protected function getDefaultHeaders()
{
    return [
        'access_token' => $_ENV['GITHUB_ACCESS_TOKEN'],
    ];
}
```

Cool, right?

You can easily use all HTTP verbs like `get`, `post` etc. It's totally hassle free. 
See more examples in the [Examples Folder](./Examples).

## Query over Response Data

Sometimes we receive huge payload as a response from the APIs. 
It's quite daunting to parse proper data from that big payload.

No worries!
We're using a powerful Query parser, named [QArray](https://github.com/nahid/qarray) by default to parse and query over the Response data.

Let's see how we can use this parser to parse the response we got for `getAllUsers` method from our previous example.

```php
public function getFirstUser()
{
    $users = $this->get('users');
    return $users->query()->from('data')->first();
}
```

We're getting list of users in the `data` key in the response. From that we're collecting the first data.
See, how easy it is!

You can find detail usage of the QArray [here](https://github.com/nahid/qarray).

Additionally, there is a secret sauce for you. 

If you don't want to query like: `$users->query()`, you can just do it like this: `$users()`. That means the response object is invokable and behave exactly like calling the `query()` method.

You're welcome. :D 

## Overriding HTTP Client

By default we are using `Guzzle` as our HTTP Client. But you are not bound to use this. You can easily use your own PSR7 supported HTTP Client with `Apiz`.
Just pass an instance of your HTTP Client to our `setClient()` method.
See an example [here](./Examples/API%20with%20Different%20Client).

Here is our GuzzleClient to get an idea how your Client should look like:
```php
<?php

namespace Apiz\Http\Clients;

use Apiz\Http\AbstractClient;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\Uri;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Message\ResponseInterface;

// Your client must extend the `AbstractClient`
class GuzzleClient extends AbstractClient
{
    public function getRequestClass()
    {
        // Return the Request class name of your PSR7 supported Client
        // This Request class must implement the Psr\Http\Message\RequestInterface
        return Request::class;
    }

    public function getResponseClass()
    {
        // Return the Response class name of your PSR7 supported Client
        // This Response class must implement the Psr\Http\Message\ResponseInterface        
        return Response::class;
    }

    public function getUriClass()
    {
        // Return the Uri class name of your PSR7 supported Client
        // This Uri class must implement the Psr\Http\Message\UriInterface        
        return Uri::class;
    }

    /**
     * @param mixed ...$args
     * @return ResponseInterface
     * @throws GuzzleException
     */
    public function send(...$args)
    {
        // In this method, implement how your Client execute the Request sending
        $client = new Client();

        return $client->send(... $args);
    }
}
```

## List of methods for common HTTP verbs

- `get(string $uri)`
- `post(string $uri)`
- `put(string $uri)`
- `delete(string $uri)`
- `head(string $uri)`
- `options(string $uri)`

## List of Available methods

- `getPrefix():string`: override this method to define the common prefix, if you need it
- `setClient($client)` : pass a PSR7 supported Client instance, only if you need to override the default Guzzle HTTP Client
- `withFormParams(array)`: pass Form parameters data for requests like POST, PATCH, UPDATE
- `withHeaders(array)`: pass Header data
- `withQueryParams(array)`: pass Query Parameter data
- `withFormData(array)`: pass Multipart form data
- `getDefaultHeaders():array`: override to define default Headers, if you have any
- `getDefaultQueries():array`: override to define default queries, if you have any
- `skipDefaultHeaders(bool)`
- `skipDefaultQueries(bool)`
- `allowRedirects(array)`
- `basicAuth(string $username, string $password [, array $options])`
- `body(string)`: Set request body
- `json(array)`: Set JSON data to be passed as Request Body
- `file(string $name, string $file_path, string $filename [, array $headers])`
- `params(array $params)`


### Contribution

Feel free send feedback and issues. Contributions to improve this package is most welcome too. PK     d,]Y&  &    LICENSEnu         MIT License

Copyright (c) 2020 nahid

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
PK     d,]Z-  -    src/HttpExceptionReceiver.phpnu         <?php

namespace Rvx\Apiz;

use Rvx\Apiz\Http\Response;
class HttpExceptionReceiver
{
    protected $exceptions;
    protected $statusCode;
    public function __construct(Response $response, $exceptions = [])
    {
        $this->statusCode = (int) $response->getStatusCode();
        $this->exceptions = $exceptions;
        $this->throwExceptions();
    }
    protected function throwExceptions()
    {
        if (\array_key_exists($this->statusCode, $this->exceptions)) {
            throw new $this->exceptions[$this->statusCode]();
        }
    }
}
PK     d,]:+U  U    src/Constants/MimeType.phpnu         <?php

namespace Rvx\Apiz\Constants;

interface MimeType
{
    const APPLICATION_JSON = 'application/json';
    const TEXT_JSON = 'text/json';
    const APPLICATION_JAVASCRIPT = 'application/javascript';
    const APPLICATION_XML = 'application/xml';
    const TEXT_XML = 'text/xml';
    const APPLICATION_YAML = 'application/x-yaml';
    const TEXT_YAML = 'text/yaml';
    const JSON_TYPES = [self::APPLICATION_JSON, self::TEXT_JSON, self::APPLICATION_JAVASCRIPT];
    const XML_TYPES = [self::APPLICATION_XML, self::TEXT_XML];
    const YAML_TYPES = [self::APPLICATION_YAML, self::TEXT_YAML];
}
PK     d,]Q@R      $  src/Constants/GraphQLRequestType.phpnu         <?php

namespace Rvx\Apiz\Constants;

interface GraphQLRequestType
{
    const QUERY = 'query';
    const MUTATION = 'mutation';
}
PK     d,]A0  0    src/AbstractApi.phpnu         <?php

declare (strict_types=1);
namespace Rvx\Apiz;

use Rvx\Apiz\GraphQL\AbstractRequest;
use Rvx\Apiz\Http\Clients\AbstractClient;
use Rvx\Apiz\Http\Clients\GuzzleClient;
use Rvx\Apiz\Http\Request;
use Rvx\Apiz\Http\Response;
use Rvx\Apiz\Traits\Hookable;
use Exception;
use Rvx\GuzzleHttp\Psr7\Utils;
use Rvx\GuzzleHttp\RequestOptions;
use Rvx\Psr\Http\Message\ResponseInterface;
use Rvx\Apiz\Exceptions\InvalidResponseClassException;
/**
 * Class AbstractApi
 * @template Resp
 * @package Apiz
 */
abstract class AbstractApi
{
    use Hookable;
    /**
     * list of available http exceptions
     *
     * @var array
     */
    protected array $httpExceptions = [];
    /**
     * skip exception when its value true
     *
     * @var bool
     */
    protected bool $shouldSkipHttpException = \false;
    /**
     * this variable contains request details
     *
     * @var Request
     */
    protected $request;
    /**
     * response class name
     * @var class-string<Resp> $response
     */
    protected $response = Response::class;
    /**
     * @var array
     */
    protected array $config = [];
    /**
     * AbstractApi constructor.
     * @param ?Request $request
     */
    public function __construct($request = null)
    {
        if (!$request || !$request->hasClient()) {
            $this->request = new Request(new GuzzleClient($this->config));
        }
        $this->setBaseURL($this->getBaseURL());
        $this->setPrefix($this->getPrefix());
    }
    /**
     * @return string
     */
    protected abstract function getBaseURL() : string;
    /**
     * Get client configs
     *
     * @return array
     */
    public function getConfig() : array
    {
        return $this->config;
    }
    /**
     * Set client config
     *
     * @param $config
     */
    public function setConfig($config)
    {
        $this->config = $config;
    }
    /**
     * Get request instance
     *
     * @return Request
     */
    public function getRequest()
    {
        return $this->request;
    }
    /**
     * set Base URL
     *
     * @param string $url
     */
    protected function setBaseURL(string $url)
    {
        $this->request->setBaseURL($url);
    }
    /**
     * @return string
     */
    public function getPrefix() : string
    {
        return '';
    }
    /**
     * set url prefix
     *
     * @param string $prefix
     */
    protected function setPrefix(string $prefix)
    {
        $this->request->setPrefix($prefix);
    }
    /**
     * @param AbstractClient $client
     */
    protected function setClient(AbstractClient $client)
    {
        $this->request->setClient($client);
    }
    /**
     * @param Request $request
     * @param ResponseInterface $response
     * @return Resp
     * @throws InvalidResponseClassException
     */
    private function makeResponse(Request $request, ResponseInterface $response)
    {
        $responseClass = $this->response;
        $apizResponse = new $responseClass($request, $response);
        if (!$apizResponse instanceof Response) {
            throw new InvalidResponseClassException();
        }
        return $apizResponse;
    }
    /**
     * @param string $responseClass
     */
    protected function setResponseClass($responseClass)
    {
        $this->response = $responseClass;
    }
    /**
     * set form parameters or form data for POST, PUT and PATCH request
     *
     * @param array $params
     * @return AbstractApi
     */
    protected function withFormParams(array $params = [])
    {
        $this->request->setContentType('application/x-www-form-urlencoded');
        $body = \urlencode(\http_build_query($params));
        $this->request->setBodyContents($body);
        return $this;
    }
    /**
     * set request headers
     *
     * @param array $headers
     * @return AbstractApi
     */
    protected function withHeaders(array $headers = []) : self
    {
        $this->request->setHeaders($headers);
        return $this;
    }
    /**
     * get default headers that will automatically bind with every request headers
     *
     * @return array
     */
    protected function getDefaultHeaders() : array
    {
        return [];
    }
    /**
     * get default queries that will automatically bind with every request
     *
     * @return array
     */
    protected function getDefaultQueries() : array
    {
        return [];
    }
    /**
     * @param bool $action
     * @return self
     */
    protected function skipDefaultHeaders(bool $action = \true) : self
    {
        $this->request->skipDefaultHeaders($action);
        return $this;
    }
    /**
     * @param bool $action
     * @return self
     */
    protected function skipDefaultQueries(bool $action = \true) : self
    {
        $this->request->skipDefaultQueries($action);
        return $this;
    }
    /**
     * set query parameters
     *
     * @param array $params
     * @return AbstractApi
     */
    protected function withQueryParams(array $params = []) : self
    {
        $this->request->setQueryParams($params);
        return $this;
    }
    protected function withOptions(array $options = []) : self
    {
        $this->request->setOptions($options);
        return $this;
    }
    /**
     * Add allow redirects param
     *
     * @param array|null $option
     * @return AbstractApi
     */
    protected function allowRedirects(?array $option = []) : self
    {
        if (empty($option)) {
            $option = \true;
        }
        $this->request->setOption(RequestOptions::ALLOW_REDIRECTS, $option);
        return $this;
    }
    /**
     * Set basic auth options
     *
     * @param string $username
     * @param string $password
     * @return AbstractApi
     */
    protected function basicAuth(string $username, string $password) : self
    {
        $this->request->setHeader('Authorization', 'Basic ' . \base64_encode("{$username}:{$password}"));
        return $this;
    }
    /**
     * Set request body
     *
     * @param mixed $contents
     * @return AbstractApi
     */
    protected function withBody($contents) : self
    {
        if (\is_array($contents)) {
            $this->request->setContentType('x-www-form-urlencoded');
            $contents = \urlencode(\http_build_query($contents));
        }
        $this->request->setBodyContents($contents);
        return $this;
    }
    /**
     * Set request param as JSON
     *
     * @param array $params
     * @return AbstractApi
     */
    protected function withJson(array $params = []) : self
    {
        $this->request->setHeader('Content-Type', 'application/json');
        $this->request->setBodyContents(\json_encode($params));
        return $this;
    }
    /**
     * Send file to the request
     *
     * @param string $name
     * @param string $file
     * @param string $filename
     * @param array $headers
     * @return AbstractApi
     */
    protected function withFile(string $name, string $file, string $filename, array $headers = []) : self
    {
        if (\file_exists($file)) {
            $contents = Utils::tryFopen($file, 'r');
            return $this->attach($name, $contents, $filename, $headers);
        }
        return $this;
    }
    /**
     * Attach a raw content with request
     *
     * @param string $name
     * @param mixed $contents
     * @param string $filename
     * @param array $headers
     * @return self
     */
    protected function attach(string $name, $contents, string $filename, array $headers = []) : self
    {
        $this->request->setBodyMultipart(['name' => $name, 'contents' => $contents, 'filename' => $filename, 'headers' => $headers]);
        return $this;
    }
    /**
     * Attach form value with multipart
     *
     * @param array $data
     * @return AbstractApi
     */
    protected function withFormData(array $data = []) : self
    {
        $params = $this->prepareFormData($data);
        if (!empty($params)) {
            $this->request->setBodyParams($params);
        }
        return $this;
    }
    /**
     * @param array $params
     * @param string $prefix
     * @return array
     */
    protected function prepareFormData(array $params, string $prefix = '') : array
    {
        $formParams = [];
        foreach ($params as $key => $value) {
            $newKey = empty($prefix) ? $key : $prefix . '[' . $key . ']';
            if (\is_array($value)) {
                $formParams = \array_merge($formParams, $this->prepareFormData($value, $newKey));
            } else {
                $formParams[] = ['name' => $newKey, 'contents' => $value];
            }
        }
        return $formParams;
    }
    /**
     * skip default http exceptions from request
     *
     * @param array $codes
     * @return AbstractApi
     */
    protected function skipHttpExceptions(array $codes = []) : self
    {
        if (!empty($codes)) {
            $this->shouldSkipHttpException = \true;
            foreach ($codes as $code) {
                unset($this->httpExceptions[$code]);
            }
        }
        return $this;
    }
    /**
     * push new http exceptions to current request
     *
     * @param array $exceptions
     * @return AbstractApi
     */
    protected function pushHttpExceptions(array $exceptions = []) : self
    {
        foreach ($exceptions as $code => $exception) {
            $this->httpExceptions[$code] = $exception;
        }
        return $this;
    }
    /**
     * @param string $uri
     * @return Resp
     * @throws Exception
     */
    protected function get(string $uri)
    {
        return $this->makeMethodRequest('GET', $uri);
    }
    /**
     * @param string $uri
     * @return Resp
     * @throws Exception
     */
    protected function post(string $uri)
    {
        return $this->makeMethodRequest('POST', $uri);
    }
    /**
     * @param string $uri
     * @return Resp
     * @throws Exception
     */
    protected function put(string $uri)
    {
        return $this->makeMethodRequest('PUT', $uri);
    }
    /**
     * @param string $uri
     * @return Resp
     * @throws Exception
     */
    protected function patch(string $uri)
    {
        return $this->makeMethodRequest('PATCH', $uri);
    }
    /**
     * @param string $uri
     * @return Resp
     * @throws Exception
     */
    protected function delete(string $uri)
    {
        return $this->makeMethodRequest('DELETE', $uri);
    }
    /**
     * @param string $uri
     * @return Resp
     * @throws Exception
     */
    protected function head(string $uri)
    {
        return $this->makeMethodRequest('HEAD', $uri);
    }
    /**
     * @param string $uri
     * @return Resp
     * @throws Exception
     */
    protected function options(string $uri)
    {
        return $this->makeMethodRequest('OPTIONS', $uri);
    }
    protected function graphqlCall(AbstractRequest $request)
    {
        return $this->graphql('', $request);
    }
    protected function graphql(string $uri, AbstractRequest $request)
    {
        return $this->withJson($request->getQuery())->post($uri);
    }
    /**
     * Make all request from here
     *
     * @param string $method
     * @param string $uri
     * @return Resp
     * @throws Exception
     */
    private function makeMethodRequest(string $method, string $uri)
    {
        $response = null;
        try {
            $this->request->setDefaultHeaders($this->getDefaultHeaders());
            $this->request->setDefaultQueries($this->getDefaultQueries());
            $request = $this->request->make($method, $uri);
            $this->executePreHooks($this->request);
            $clientResponse = $this->request->send($request);
            $response = $this->makeResponse($this->request, $clientResponse);
            if (!$this->shouldSkipHttpException) {
                if ($response instanceof Response) {
                    new HttpExceptionReceiver($response, $this->httpExceptions);
                }
            }
            $this->executeSuccessHooks($response, $this->request);
        } catch (Exception $e) {
            $this->executeFailHooks($e);
            throw $e;
        } finally {
            $this->resetObjects();
        }
        return $response;
    }
    /**
     * Reset this class objects
     */
    protected function resetObjects()
    {
        $this->shouldSkipHttpException = \false;
        $this->request->reset();
    }
}
PK     d,]'t&  &    src/Http/Request.phpnu         <?php

namespace Rvx\Apiz\Http;

use Rvx\Apiz\GraphQL\AbstractRequest;
use Rvx\Apiz\Http\Clients\AbstractClient;
use Rvx\Apiz\Http\Clients\GuzzleClient;
use Exception;
use Rvx\Apiz\Exceptions\ClientNotDefinedException;
use Rvx\Apiz\Exceptions\InvalidResponseClassException;
use Rvx\GuzzleHttp\Psr7\MultipartStream;
use Rvx\Psr\Http\Message\RequestInterface;
use Rvx\Psr\Http\Message\ResponseInterface;
class Request
{
    /**
     * The main client to do all the magic
     *
     * @var AbstractClient
     */
    protected $client = null;
    /**
     * Base URL
     *
     * @var string
     */
    private $baseUrl = '';
    /**
     * URL prefix
     *
     * @var string
     */
    private $prefix = '';
    /**
     * Default headers options for request
     *
     * @var array
     */
    private $defaultHeaders = [];
    /**
     * Default Query options for request
     *
     * @var array
     */
    private $defaultQueries = [];
    /**
     * when need to skip default header make it true
     *
     * @var bool
     */
    private $shouldSkipDefaultHeader = \false;
    /**
     * when need to skip default query make it true
     *
     * @var bool
     */
    private $shouldSkipDefaultQueries = \false;
    /**
     * Options for http clients
     *
     * @var array
     */
    protected $options = [];
    /**
     * Request parameters
     *
     * @var array
     */
    protected $body = [];
    /**
     * Query parameters
     *
     * @var array
     */
    protected $queryParams = [];
    protected $headers = [];
    protected $contentType = 'application/x-www-form-urlencoded';
    /**
     * @var RequestInterface
     */
    protected RequestInterface $psrRequest;
    public function __construct(AbstractClient $client = null)
    {
        if (!$client) {
            $client = new GuzzleClient();
        }
        $this->setClient($client);
    }
    /**
     * @return AbstractClient
     * @throws ClientNotDefinedException
     */
    public function getClient() : AbstractClient
    {
        if (!$this->client) {
            throw new ClientNotDefinedException();
        }
        return $this->client;
    }
    /**
     * @param AbstractClient $client
     */
    public function setClient(AbstractClient $client) : void
    {
        $this->client = $client;
    }
    /**
     * check if client is set
     *
     * @return bool
     */
    public function hasClient() : bool
    {
        return !!$this->client;
    }
    /**
     * get Base URL
     *
     * @return string
     */
    public function getBaseURL() : string
    {
        return \trim($this->baseUrl, '/');
    }
    /**
     * set Base URL
     *
     * @param string $url
     */
    public function setBaseURL(string $url) : void
    {
        $this->baseUrl = $url;
    }
    /**
     * get url prefix
     *
     * @return string
     */
    public function getPrefix() : string
    {
        return \trim($this->prefix, '/');
    }
    /**
     * set url prefix
     *
     * @param string $prefix
     */
    public function setPrefix(string $prefix) : void
    {
        $this->prefix = $prefix;
    }
    /**
     * get default headers that will automatically bind with every request headers
     *
     * @return array
     */
    protected function getDefaultHeaders() : array
    {
        return $this->defaultHeaders;
    }
    /**
     * set default headers that will automatically bind with every request headers
     *
     * @param array $headers
     */
    public function setDefaultHeaders(array $headers) : void
    {
        $this->defaultHeaders = $headers;
    }
    /**
     * get default queries that will automatically bind with every request
     *
     * @return array
     */
    protected function getDefaultQueries() : array
    {
        return $this->defaultQueries;
    }
    /**
     * set default queries that will automatically bind with every request
     *
     * @param array $queries
     */
    public function setDefaultQueries(array $queries) : void
    {
        $this->defaultQueries = $queries;
    }
    /**
     * @return array
     */
    public function getOptions() : array
    {
        return $this->options;
    }
    /**
     * @param array $options
     */
    public function setOptions(array $options) : void
    {
        $this->options = $options;
    }
    /**
     * @param string $name
     * @param mixed $option
     */
    public function setOption(string $name, $option) : void
    {
        $this->options[$name] = $option;
    }
    /**
     * @return mixed
     */
    public function getBodyContents()
    {
        return $this->body;
    }
    /**
     * @param mixed $contents
     * @return  void
     */
    public function setBodyContents($contents) : void
    {
        $this->body = $contents;
    }
    public function setBodyParam(string $key, $value) : void
    {
        if (!\is_array($this->body)) {
            $this->body = [];
        }
        $this->body[$key] = $value;
    }
    public function setBodyParams(array $params) : void
    {
        $this->body = $params;
    }
    public function setBodyMultipart(array $value) : void
    {
        $this->setContentType('multipart/form-data');
        if (!\is_array($this->body)) {
            $this->body = [];
        }
        $this->body[] = $value;
    }
    /**
     * @param bool $action
     * @return Request
     */
    public function skipDefaultHeaders(bool $action = \true) : self
    {
        $this->shouldSkipDefaultHeader = $action;
        return $this;
    }
    /**
     * @param bool $action
     * @return Request
     */
    public function skipDefaultQueries(bool $action = \true) : self
    {
        $this->shouldSkipDefaultQueries = $action;
        return $this;
    }
    public function setContentType(string $type) : void
    {
        $this->contentType = $type;
        if ($type == 'multipart/form-data') {
            return;
        }
        $this->setHeader('Content-Type', $type);
    }
    public function getHeaders() : array
    {
        return $this->headers;
    }
    public function getHeader(string $key) : ?string
    {
        return $this->headers[$key] ?? null;
    }
    public function setHeaders(array $headers) : void
    {
        $this->headers = $headers;
    }
    public function setHeader(string $key, string $value) : void
    {
        $this->headers[$key] = $value;
    }
    public function hasHeader(string $key) : bool
    {
        return isset($this->headers[$key]);
    }
    public function getQueryParams() : array
    {
        return $this->queryParams;
    }
    public function getQueryParam(string $key) : ?string
    {
        return $this->queryParams[$key] ?? null;
    }
    public function setQueryParams(array $queryParams) : void
    {
        $this->queryParams = $queryParams;
    }
    public function setQueryParam(string $key, string $value) : void
    {
        $this->queryParams[$key] = $value;
    }
    public function hasQueryParam(string $key) : bool
    {
        return isset($this->queryParams[$key]);
    }
    protected function mergeDefaultHeaders() : void
    {
        if ($this->shouldSkipDefaultHeader) {
            return;
        }
        $this->setHeaders(\array_merge($this->defaultHeaders, $this->getHeaders()));
    }
    protected function mergeDefaultQueries() : void
    {
        if ($this->shouldSkipDefaultQueries) {
            return;
        }
        $this->setQueryParams(\array_merge($this->defaultQueries, $this->getQueryParams()));
    }
    /**
     * @param string $method
     * @param string $uri
     * @return RequestInterface
     * @throws ClientNotDefinedException
     */
    public function make(string $method, string $uri) : RequestInterface
    {
        $this->mergeDefaultHeaders();
        $this->mergeDefaultQueries();
        $fullPath = $this->getFullRequestPath($uri);
        $uriObject = $this->getClient()->getUri($fullPath);
        $body = $this->getBodyContents();
        if (\is_array($body) && $this->contentType == 'multipart/form-data') {
            $body = new MultipartStream($body);
        }
        if (\is_array($body)) {
            $body = \urlencode(\http_build_query($body));
        }
        if (\strtoupper($method) === 'GET') {
            $body = '';
        }
        $this->psrRequest = $this->getClient()->getRequest($method, $uriObject, $this->getHeaders(), $body);
        return $this->psrRequest;
    }
    public function getPsrRequest() : RequestInterface
    {
        return $this->psrRequest;
    }
    /**
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws ClientNotDefinedException
     * @throws InvalidResponseClassException
     */
    public function send(RequestInterface $request) : ResponseInterface
    {
        $response = $this->getClient()->send($request, $this->getOptions());
        if (!$this->getClient()->isValidResponse($response)) {
            throw new InvalidResponseClassException();
        }
        return $response;
    }
    /**
     * @param string $uri
     * @return string
     */
    public function getFullRequestPath(string $uri) : string
    {
        $uri = \trim($uri, '/');
        $prefix = $this->getPrefix();
        $baseUrl = $this->getBaseURL();
        if ($prefix) {
            $uri = "{$prefix}/{$uri}";
        }
        $params = '';
        if (!empty($this->queryParams)) {
            $params = '?' . \http_build_query($this->queryParams);
        }
        return "{$baseUrl}/{$uri}{$params}";
    }
    public function reset() : void
    {
        $this->shouldSkipDefaultHeader = \false;
        $this->shouldSkipDefaultQueries = \false;
        $this->options = [];
        $this->body = [];
        $this->queryParams = [];
        $this->headers = [];
        $this->contentType = 'application/x-www-form-urlencoded';
    }
}
PK     d,]!    #  src/Http/Clients/AbstractClient.phpnu         <?php

namespace Rvx\Apiz\Http\Clients;

use Exception;
use Rvx\Psr\Http\Message\RequestInterface;
use Rvx\Psr\Http\Message\ResponseInterface;
use Rvx\Psr\Http\Message\UriInterface;
abstract class AbstractClient
{
    /**
     * @var array
     */
    protected $config;
    public function __construct($config = [])
    {
        $this->config = $config;
    }
    /**
     * @return string
     */
    protected abstract function getRequestClass() : string;
    /**
     * @return string
     */
    protected abstract function getResponseClass() : string;
    /**
     * @return string
     */
    protected abstract function getUriClass() : string;
    /**
     * @param array $args
     * @return ResponseInterface
     * @throws Exception
     */
    public abstract function send(...$args) : ResponseInterface;
    /**
     * @param mixed ...$args
     * @return RequestInterface
     */
    public function getRequest(...$args)
    {
        $class = $this->getRequestClass();
        return new $class(...$args);
    }
    /**
     * @param mixed ...$args
     * @return ResponseInterface
     */
    public function getResponse(...$args)
    {
        $class = $this->getResponseClass();
        return new $class(...$args);
    }
    /**
     * @param mixed ...$args
     * @return UriInterface
     */
    public function getUri(...$args)
    {
        $class = $this->getUriClass();
        return new $class(...$args);
    }
    /**
     * @param ResponseInterface $response
     * @return bool
     */
    public function isValidResponse(ResponseInterface $response)
    {
        $responseClass = $this->getResponseClass();
        if ($response instanceof $responseClass) {
            return \true;
        }
        return \false;
    }
}
PK     d,]-    !  src/Http/Clients/GuzzleClient.phpnu         <?php

namespace Rvx\Apiz\Http\Clients;

use Rvx\GuzzleHttp\Client;
use Rvx\GuzzleHttp\Psr7\Request;
use Rvx\GuzzleHttp\Psr7\Response;
use Rvx\GuzzleHttp\Psr7\Uri;
use Rvx\GuzzleHttp\Exception\GuzzleException;
use Rvx\Psr\Http\Message\RequestInterface;
use Rvx\Psr\Http\Message\ResponseInterface;
class GuzzleClient extends AbstractClient
{
    /**
     * @inheritDoc
     * @return string
     */
    public function getRequestClass() : string
    {
        return Request::class;
    }
    /**
     * @inheritDoc
     */
    public function getResponseClass() : string
    {
        return Response::class;
    }
    /**
     * @inheritDoc
     */
    public function getUriClass() : string
    {
        return Uri::class;
    }
    /**
     * @param mixed ...$args
     * @return ResponseInterface
     * @throws GuzzleException
     */
    public function send(...$args) : ResponseInterface
    {
        $client = new Client($this->config);
        return $client->send(...$args);
    }
}
PK     d,]ċg      src/Http/Response.phpnu         <?php

namespace Rvx\Apiz\Http;

use Exception;
use Rvx\Nahid\QArray\QueryEngine;
use Rvx\Apiz\Exceptions\NoResponseException;
use Rvx\Apiz\QueryBuilder;
use Rvx\Apiz\Utilities\Parser;
use Rvx\Psr\Http\Message\ResponseInterface;
use Rvx\Psr\Http\Message\StreamInterface;
class Response
{
    /**
     * store response object
     *
     * @var ResponseInterface
     */
    protected $response;
    /**
     * Store request details
     *
     * @var Request
     */
    protected $request;
    /**
     * Store raw contents
     *
     * @var mixed|string
     */
    protected $rawContent = '';
    /**
     * instance of QueryBuilder
     *
     * @var null|QueryBuilder
     */
    protected $queryBuilder = null;
    /**
     * Response constructor.
     *
     * @param Request $request
     * @param ResponseInterface $response
     * @throws NoResponseException
     */
    public function __construct(Request $request, ResponseInterface $response)
    {
        $this->setRequest($request);
        $this->setResponse($response);
        $this->rawContent = $this->fetchContents();
    }
    /**
     * This is to make the response invokable and behave properly to Query calls
     * e.g. With the $response, user can now call $response()->from('node')->get();
     *
     * @return QueryEngine
     * @throws Exception
     */
    public function __invoke()
    {
        return $this->query();
    }
    public function __toString()
    {
        return (string) $this->rawContent;
    }
    /**
     * Get requests details
     *
     * @return Request
     */
    protected function getRequest()
    {
        return $this->request;
    }
    /**
     * @param Request $request
     */
    protected function setRequest(Request $request)
    {
        $this->request = $request;
    }
    /**
     * @param ResponseInterface $response
     * @throws NoResponseException
     */
    protected function setResponse(ResponseInterface $response)
    {
        if (\is_null($response)) {
            throw new NoResponseException();
        }
        $this->response = $response;
    }
    /**
     * Automatically parse response contents based on mime type
     *
     * @return array|bool|mixed|SimpleXMLElement|string
     */
    public function autoParse()
    {
        return Parser::parseByMimeType($this->getContents(), $this->getMimeType());
    }
    /**
     * Fetch response raw contents
     *
     * @return mixed
     */
    private function fetchContents()
    {
        return $this->getBody()->getContents();
    }
    /**
     * @return int
     */
    public function getStatusCode()
    {
        return $this->response->getStatusCode();
    }
    /**
     * @return array
     */
    public function getHeaders()
    {
        return $this->response->getHeaders();
    }
    /**
     * @param $name
     * @return string[]
     */
    public function getHeader($name)
    {
        return $this->response->getHeader($name);
    }
    /**
     * @param $name
     * @return bool
     */
    public function hasHeader($name)
    {
        return $this->response->hasHeader($name);
    }
    /**
     * @param $name
     * @return string
     */
    public function getHeaderLine($name)
    {
        return $this->response->getHeaderLine($name);
    }
    /**
     * @return StreamInterface
     */
    public function getBody()
    {
        return $this->response->getBody();
    }
    /**
     * Get response data mime types
     *
     * @return array
     */
    public function getMimeTypes()
    {
        $content_types = $this->response->getHeader('Content-Type');
        if (\count($content_types) > 0) {
            return \explode(';', $content_types[0]);
        }
        return [];
    }
    /**
     * Get response data mime type
     *
     * @return string
     */
    public function getMimeType()
    {
        $header = $this->getMimeTypes();
        if (\count($header) > 0) {
            return $header[0];
        }
        return null;
    }
    /**
     * Getter for contents
     *
     * @return mixed|string
     */
    public function getContents()
    {
        return $this->rawContent;
    }
    /**
     * get the response body size
     *
     * @return int
     */
    public function size()
    {
        $lengths = $this->getHeader('Content-Length');
        if (\count($lengths) > 0) {
            return (int) $lengths[0];
        }
        return 0;
    }
    /**
     * check is response empty
     * 
     * @return bool
     */
    public function isEmpty()
    {
        return (bool) $this->size();
    }
    /**
     * make QueryBuilder instance from response
     */
    protected function initQueryBuilder()
    {
        if (\is_null($this->queryBuilder)) {
            $this->queryBuilder = new QueryBuilder();
            $parsedContent = $this->autoParse();
            if ($parsedContent) {
                $this->queryBuilder = $this->queryBuilder->collect($parsedContent);
            }
        }
    }
    /**
     * return QueryBuilder instance from response
     *
     * @return QueryEngine
     * @throws Exception
     */
    public function query()
    {
        $this->initQueryBuilder();
        return $this->queryBuilder;
    }
    /**
     * @return QueryEngine
     */
    public function reset()
    {
        return $this->queryBuilder->reset(null, \true);
    }
}
PK     d,]Q	  	    src/Traits/Hookable.phpnu         <?php

namespace Rvx\Apiz\Traits;

trait Hookable
{
    /**
     * @var callable
     */
    private $preHookFn = null;
    /**
     * @var callable
     */
    private $successHookFn = null;
    /**
     * @var callable
     */
    private $failsHookFn = null;
    /**
     * @return callable
     */
    public function getPreHookFn()
    {
        return $this->preHookFn;
    }
    /**
     * @param callable
     *
     * @return Hookable
     */
    public function bindPreHook(callable $fn)
    {
        $this->preHookFn = $fn;
        return $this;
    }
    /**
     * @return callable
     */
    public function getSuccessHookFn()
    {
        return $this->successHookFn;
    }
    /**
     * @param callable
     *
     * @return Hookable
     */
    public function bindSuccessHook(callable $fn)
    {
        $this->successHookFn = $fn;
        return $this;
    }
    /**
     * @return callable
     */
    public function getFailsHookFn()
    {
        return $this->failsHookFn;
    }
    /**
     * @param callable
     *
     * @return Hookable
     */
    public function bindFailsHook(callable $fn)
    {
        $this->failsHookFn = $fn;
        return $this;
    }
    protected function preHook($request)
    {
        return;
    }
    protected function successHook($response, $request)
    {
        return;
    }
    protected function failsHook($exception)
    {
        return;
    }
    /**
     * @param $request
     */
    private function executePreHooks($request)
    {
        if (\is_null($this->preHookFn)) {
            $this->preHook($request);
        }
        if (\is_callable($this->preHookFn)) {
            $preHookFn = $this->preHookFn;
            $preHookFn($request);
        }
    }
    /**
     * @param $response
     * @param $request
     */
    private function executeSuccessHooks($response, $request)
    {
        if (\is_null($this->successHookFn)) {
            $this->successHook($response, $request);
        }
        if (\is_callable($this->successHookFn)) {
            $successHookFn = $this->successHookFn;
            $successHookFn($response, $request);
        }
    }
    /**
     * @param $exceptions
     */
    private function executeFailHooks($exceptions)
    {
        if (\is_null($this->failsHookFn)) {
            $this->failsHook($exceptions);
        }
        if (\is_callable($this->failsHookFn)) {
            $failsHookFn = $this->failsHookFn;
            $failsHookFn($exceptions);
        }
    }
}
PK     d,]m4  4    src/QueryBuilder.phpnu         <?php

namespace Rvx\Apiz;

use Rvx\Nahid\QArray\QueryEngine;
class QueryBuilder extends QueryEngine
{
    public function parseData($data)
    {
        if (\is_array($data)) {
            return $data;
        }
        return [];
    }
    public function readPath($path)
    {
        return [];
    }
}
PK     d,]Dm!Ʀ      src/GraphQL/AbstractRequest.phpnu         <?php

namespace Rvx\Apiz\GraphQL;

use Rvx\Apiz\Constants\GraphQLRequestType;
abstract class AbstractRequest
{
    protected array $variables = [];
    public abstract function query() : string;
    public function getVariables() : array
    {
        return $this->variables;
    }
    public function getType() : string
    {
        $query = \trim($this->query());
        $words = \explode(' ', $query, 2);
        if (isset($words[0]) && isset($words[1])) {
            $type = \strtolower($words[0]);
            if ($type === GraphQLRequestType::QUERY || $type === GraphQLRequestType::MUTATION) {
                return $type;
            }
        }
        throw new \InvalidArgumentException('Invalid query type');
    }
    public function getQuery() : array
    {
        $query = ['query' => $this->query()];
        if (!empty($this->getVariables())) {
            $query['variables'] = $this->getVariables();
        }
        return $query;
    }
    public function setVariables(array $variables) : self
    {
        $this->variables = $variables;
        return $this;
    }
    public function __toString()
    {
        return \json_encode($this->getQuery());
    }
}
PK     d,]b      src/GraphQL/GraphQLRequest.phpnu         <?php

declare (strict_types=1);
namespace Rvx\Apiz\GraphQL;

class GraphQLRequest extends AbstractRequest
{
    protected string $query;
    protected array $variables;
    public function __construct(string $query, array $variables = [])
    {
        $this->query = $query;
        $this->variables = $variables;
    }
    public function query() : string
    {
        return $this->query;
    }
    public function variables() : array
    {
        return $this->variables;
    }
}
PK     d,]8      src/Utilities/Parser.phpnu         <?php

namespace Rvx\Apiz\Utilities;

use SimpleXMLElement;
use Rvx\Apiz\Constants\MimeType;
class Parser
{
    /**
     * @param $content
     * @param $mimeType
     * @return array|bool|mixed|SimpleXMLElement|string
     */
    public static function parseByMimeType($content, $mimeType)
    {
        if (\in_array($mimeType, MimeType::JSON_TYPES)) {
            return self::parseJson($content, \true);
        } elseif (\in_array($mimeType, MimeType::XML_TYPES)) {
            return self::parseXml($content);
        } elseif (\in_array($mimeType, MimeType::XML_TYPES)) {
            return self::parseYaml($content);
        }
        return $content;
    }
    /**
     * Parse raw contents to JSON
     *
     * @param string $content
     * @param bool $toAssoc
     * @return bool|mixed|string
     */
    private static function parseJson($content, $toAssoc = \false)
    {
        $content = \json_decode($content, $toAssoc);
        if (\json_last_error() == \JSON_ERROR_NONE) {
            return $content;
        }
        return \false;
    }
    /**
     * Parse raw contents to XML
     *
     * @param string $content
     * @return array|SimpleXMLElement
     */
    private static function parseXml($content)
    {
        \libxml_use_internal_errors(\true);
        $elem = \simplexml_load_string($content);
        if ($elem === \false) {
            return \libxml_get_errors();
        }
        return self::xml2array($elem);
    }
    /**
     * @param $data
     * @return array
     */
    private static function xml2array($data)
    {
        $out = [];
        foreach ((array) $data as $key => $node) {
            $out[$key] = \is_object($node) ? self::xml2array($node) : $node;
        }
        return $out;
    }
    /**
     * Parse raw contents to Yaml
     *
     * @param string $content
     * @return mixed
     */
    private static function parseYaml($content)
    {
        return \yaml_parse($content);
    }
}
PK     d,]NT    ,  src/Exceptions/ClientNotDefinedException.phpnu         <?php

namespace Rvx\Apiz\Exceptions;

use Exception;
class ClientNotDefinedException extends Exception
{
    public function __construct($message = "Client Not Defined", $code = 0, $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}
PK     d,]t"  "  &  src/Exceptions/NoResponseException.phpnu         <?php

namespace Rvx\Apiz\Exceptions;

use Exception;
class NoResponseException extends Exception
{
    public function __construct($message = "Connection timeout or no response exception", $code = 0, $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}
PK     d,]h    0  src/Exceptions/InvalidResponseClassException.phpnu         <?php

namespace Rvx\Apiz\Exceptions;

use Exception;
class InvalidResponseClassException extends Exception
{
    public function __construct($message = "Invalid Response Class", $code = 0, $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}
PK     d,]ӝ B  B    composer.jsonnu         {
    "name": "nahid\/apiz",
    "description": "Apiz is a boilerplate for REST API HTTP call manager",
    "type": "php",
    "require": {
        "php": ">=7.4",
        "ext-json": "*",
        "lib-libxml": ">=2.6.20",
        "nahid\/qarray": "^2.1",
        "guzzlehttp\/guzzle": "^6.0 | ^7.0"
    },
    "require-dev": {
        "phpunit\/phpunit": "^9",
        "symfony\/var-dumper": "^5.1"
    },
    "suggest": {
        "ext-curl": "*",
        "ext-libxml": "*",
        "ext-yaml": "*",
        "ext-simplexml": "*"
    },
    "license": "MIT",
    "authors": [
        {
            "name": "Nahid Bin Azhar",
            "email": "nahid.dns@gmail.com"
        },
        {
            "name": "Ahmed shamim",
            "email": "shaon.cse81@gmail.com"
        }
    ],
    "autoload": {
        "psr-4": {
            "Rvx\\Apiz\\": "src\/",
            "Rvx\\Tests\\": "Tests\/"
        },
        "files": []
    },
    "minimum-stability": "stable",
    "autoload-dev": {
        "psr-4": {
            "Rvx\\Api\\": "api\/"
        }
    },
    "prefer-stable": true
}PK     d,]lQh    '  Tests/Feature/BasicHTTPRequestsTest.phpnu         <?php

namespace Rvx\Tests\Feature;

use Rvx\Apiz\Http\Response;
use Rvx\PHPUnit\Framework\TestCase;
use Rvx\Tests\Feature\Mocks\BasicHTTPAPI;
class BasicHTTPRequestsTest extends TestCase
{
    public function testGet()
    {
        $exampleAPI = $this->getBasicHTTPAPIMock();
        $users = $exampleAPI->getAllUsers();
        $this->assertInstanceOf(Response::class, $users);
    }
    public function testPost()
    {
        $exampleAPI = $this->getBasicHTTPAPIMock();
        $user = $exampleAPI->createUser(['name' => "John Doe", 'designation' => "Spy"]);
        $this->assertInstanceOf(Response::class, $user);
    }
    public function testPut()
    {
        $exampleAPI = $this->getBasicHTTPAPIMock();
        $user = $exampleAPI->updateUser(['name' => "Jane Doe", 'designation' => "Super Spy"]);
        $this->assertInstanceOf(Response::class, $user);
    }
    public function testPatch()
    {
        $exampleAPI = $this->getBasicHTTPAPIMock();
        $user = $exampleAPI->partiallyUpdateUser(['name' => "James Bond"]);
        $this->assertInstanceOf(Response::class, $user);
    }
    public function testDelete()
    {
        $exampleAPI = $this->getBasicHTTPAPIMock();
        $user = $exampleAPI->deleteUser(2);
        $this->assertInstanceOf(Response::class, $user);
    }
    /**
     * @return BasicHTTPAPI
     */
    protected function getBasicHTTPAPIMock()
    {
        return new BasicHTTPAPI();
    }
}
PK     d,].    $  Tests/Feature/Mocks/BasicHTTPAPI.phpnu         <?php

namespace Rvx\Tests\Feature\Mocks;

use Rvx\Apiz\AbstractApi;
class BasicHTTPAPI extends AbstractApi
{
    protected function getBaseURL()
    {
        return 'https://reqres.in';
    }
    public function getPrefix()
    {
        return 'api';
    }
    public function getAllUsers()
    {
        return $this->get('users');
    }
    public function createUser(array $data)
    {
        return $this->withJson($data)->post('users');
    }
    public function updateUser(array $data)
    {
        return $this->withJson($data)->put('users');
    }
    public function partiallyUpdateUser(array $data)
    {
        return $this->withJson($data)->patch('users');
    }
    public function deleteUser($id)
    {
        return $this->delete("users/{$id}");
    }
}
PK     d,]!F7T    .  Examples/API with Different Client/BaseAPI.phpnu         <?php

namespace Rvx\Examples;

use Rvx\Apiz\AbstractApi;
abstract class BaseAPI extends AbstractApi
{
    public function __construct()
    {
        parent::__construct();
        // Just pass an instance of your own PSR7 supported client like this
        $this->setClient(new MyAwesomeClient());
    }
    /**
     * @inheritDoc
     */
    protected function getBaseURL()
    {
        return 'https://reqres.in';
    }
    protected function getPrefix()
    {
        return 'api';
    }
}
PK     d,]S      1  Examples/API with Different Client/ExampleAPI.phpnu         <?php

namespace Rvx\Examples;

class ExampleAPI extends BaseAPI
{
    public function getAllUsers()
    {
        return $this->get('users');
    }
}
PK     d,]7&#  #  ,  Examples/Basic HTTP Example/BasicHTTPAPI.phpnu         <?php

namespace Rvx\Examples;

use Rvx\Apiz\AbstractApi;
class BasicHTTPAPI extends AbstractApi
{
    /**
     * @inheritDoc
     */
    protected function getBaseURL()
    {
        return 'https://reqres.in';
    }
    protected function getPrefix()
    {
        return 'api';
    }
    public function getAllUsers()
    {
        return $this->get('users');
    }
    public function createUser(array $data)
    {
        return $this->withJson($data)->post('users');
    }
    public function updateUser(array $data)
    {
        return $this->withJson($data)->put('users');
    }
    public function partiallyUpdateUser(array $data)
    {
        return $this->withJson($data)->patch('users');
    }
    public function deleteUser($id)
    {
        return $this->delete("users/{$id}");
    }
}
PK       d,]    	                readme.mdnu         PK       d,]Y&  &                LICENSEnu         PK       d,]Z-  -              d   src/HttpExceptionReceiver.phpnu         PK       d,]:+U  U              "  src/Constants/MimeType.phpnu         PK       d,]Q@R      $            }%  src/Constants/GraphQLRequestType.phpnu         PK       d,]A0  0              T&  src/AbstractApi.phpnu         PK       d,]'t&  &              'W  src/Http/Request.phpnu         PK       d,]!    #            ~  src/Http/Clients/AbstractClient.phpnu         PK       d,]-    !            5  src/Http/Clients/GuzzleClient.phpnu         PK       d,]ċg                i  src/Http/Response.phpnu         PK       d,]Q	  	                src/Traits/Hookable.phpnu         PK       d,]m4  4                src/QueryBuilder.phpnu         PK       d,]Dm!Ʀ                  src/GraphQL/AbstractRequest.phpnu         PK       d,]b                  src/GraphQL/GraphQLRequest.phpnu         PK       d,]8                I  src/Utilities/Parser.phpnu         PK       d,]NT    ,            :  src/Exceptions/ClientNotDefinedException.phpnu         PK       d,]t"  "  &              src/Exceptions/NoResponseException.phpnu         PK       d,]h    0              src/Exceptions/InvalidResponseClassException.phpnu         PK       d,]ӝ B  B                composer.jsonnu         PK       d,]lQh    '              Tests/Feature/BasicHTTPRequestsTest.phpnu         PK       d,].    $            	  Tests/Feature/Mocks/BasicHTTPAPI.phpnu         PK       d,]!F7T    .            e  Examples/API with Different Client/BaseAPI.phpnu         PK       d,]S      1              Examples/API with Different Client/ExampleAPI.phpnu         PK       d,]7&#  #  ,              Examples/Basic HTTP Example/BasicHTTPAPI.phpnu         PK        * 