Skip to content

Commit 5de24fc

Browse files
authored
Merge pull request #18 from resendlabs/feat-new-api-endpoints
2 parents 4518745 + 5fa6740 commit 5de24fc

28 files changed

+764
-138
lines changed

.php-cs-fixer.php

+4
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@
113113
'positions' => ['inside', 'outside'],
114114
],
115115
'no_spaces_inside_parenthesis' => true,
116+
'no_superfluous_phpdoc_tags' => [
117+
'allow_mixed' => true,
118+
'allow_unused_params' => true,
119+
],
116120
'no_trailing_comma_in_list_call' => true,
117121
'no_trailing_comma_in_singleline_array' => true,
118122
'no_trailing_whitespace' => true,

phpunit.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
<directory suffix=".php">./tests</directory>
1010
</testsuite>
1111
</testsuites>
12-
<coverage>
12+
<source>
1313
<include>
1414
<directory suffix=".php">./src</directory>
1515
</include>
16-
</coverage>
16+
</source>
1717
</phpunit>

src/ApiKey.php

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Resend;
4+
5+
/**
6+
* @property string $id The unique identifier for the API key.
7+
* @property string $name The name of the API key.
8+
* @property string $created_at Time at which the API key was created.
9+
* @property string|null $token The new API key to authenticate request with Resend.
10+
*/
11+
final class ApiKey extends Resource
12+
{
13+
//
14+
}

src/Client.php

+34-3
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,22 @@
33
namespace Resend;
44

55
use Resend\Contracts\Transporter;
6-
use Resend\Responses\Email\Sent;
6+
use Resend\Service\ServiceFactory;
77
use Resend\ValueObjects\Transporter\Payload;
88

9+
/**
10+
* Client used to send requests to the Resend API.
11+
*
12+
* @property \Resend\Service\ApiKey $apiKeys
13+
* @property \Resend\Service\Domain $domains
14+
*/
915
class Client
1016
{
17+
/**
18+
* The service factory instance.
19+
*/
20+
private ServiceFactory $serviceFactory;
21+
1122
/**
1223
* Create a new Client instance with the given transporter.
1324
*/
@@ -22,12 +33,32 @@ public function __construct(
2233
*
2334
* @see https://resend.com/docs/api-reference/send-email#body-parameters
2435
*/
25-
public function sendEmail(array $parameters): Sent
36+
public function sendEmail(array $parameters): Email
2637
{
2738
$payload = Payload::create('email', $parameters);
2839

2940
$result = $this->transporter->request($payload);
3041

31-
return Sent::from($result);
42+
return Email::from($result);
43+
}
44+
45+
/**
46+
* Magic method to retrieve a service by name.
47+
*/
48+
public function __get(string $name)
49+
{
50+
return $this->getService($name);
51+
}
52+
53+
/**
54+
* Attach the given API service to the client.
55+
*/
56+
private function getService(string $name)
57+
{
58+
if (! isset($this->serviceFactory)) {
59+
$this->serviceFactory = new ServiceFactory($this->transporter);
60+
}
61+
62+
return $this->serviceFactory->getService($name);
3263
}
3364
}

src/Collection.php

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Resend;
4+
5+
use ArrayIterator;
6+
use InvalidArgumentException;
7+
use IteratorAggregate;
8+
use Traversable;
9+
10+
/**
11+
* @template TResource of Resource
12+
* @template-implements \IteratorAggregate<TResource>
13+
*
14+
* @property TResource[] $data
15+
*/
16+
final class Collection extends Resource implements IteratorAggregate
17+
{
18+
/**
19+
* {@inheritdoc}
20+
*/
21+
public function getIterator(): Traversable
22+
{
23+
return new ArrayIterator($this->data);
24+
}
25+
26+
/**
27+
* {@inheritdoc}
28+
*/
29+
public function offsetGet(mixed $offset): mixed
30+
{
31+
if (is_string($offset)) {
32+
return parent::offsetGet($offset);
33+
}
34+
35+
throw new InvalidArgumentException("You tried to access the {$offset} index, but Collection types only support string keys.");
36+
}
37+
}

src/Concerns/ArrayAccessible.php

-40
This file was deleted.

src/Contracts/Resource.php

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Resend\Contracts;
4+
5+
use ArrayAccess;
6+
use JsonSerializable;
7+
8+
interface Resource extends ArrayAccess, JsonSerializable
9+
{
10+
//
11+
}

src/Domain.php

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Resend;
4+
5+
final class Domain extends Resource
6+
{
7+
//
8+
}

src/Email.php

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Resend;
4+
5+
/**
6+
* @property string $id The unique identifier for the API key.
7+
* @property string $from The sender's email address.
8+
* @property string $to The email recipient address.
9+
* @property string $created_at Time at which the API key was created.
10+
*/
11+
final class Email extends Resource
12+
{
13+
//
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Resend\Exceptions;
4+
5+
use OutOfBoundsException;
6+
7+
class MissingAttributeException extends OutOfBoundsException
8+
{
9+
//
10+
}

src/Resource.php

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?php
2+
3+
namespace Resend;
4+
5+
use BadMethodCallException;
6+
use Resend\Contracts\Resource as ResourceContract;
7+
use Resend\Exceptions\MissingAttributeException;
8+
9+
class Resource implements ResourceContract
10+
{
11+
/**
12+
* The resources's attributes.
13+
*/
14+
protected $attributes = [];
15+
16+
/**
17+
* Create a new Resource instance.
18+
*/
19+
public function __construct(array $attributes = [])
20+
{
21+
$this->fill($attributes);
22+
}
23+
24+
/**
25+
* Create a new resource from the given attributes.
26+
*/
27+
public static function from(array $attributes): static
28+
{
29+
return new static($attributes);
30+
}
31+
32+
/**
33+
* Fill the resource with an array of attributes.
34+
*/
35+
protected function fill(array $attributes): void
36+
{
37+
$fillable = $attributes;
38+
39+
foreach ($fillable as $key => $value) {
40+
$this->attributes[$key] = $value;
41+
}
42+
}
43+
44+
/**
45+
* Get an attribute by name.
46+
*/
47+
public function getAttribute($name)
48+
{
49+
if (! $name) {
50+
return;
51+
}
52+
53+
if (array_key_exists($name, $this->attributes)) {
54+
return $this->getAttributes()[$name] ?? null;
55+
}
56+
57+
return null;
58+
}
59+
60+
/**
61+
* Get all attributes for the resource.
62+
*/
63+
public function getAttributes(): array
64+
{
65+
return $this->attributes;
66+
}
67+
68+
/**
69+
* Convert the resource instance into an array.
70+
*/
71+
public function toArray(): array
72+
{
73+
return $this->getAttributes();
74+
}
75+
76+
/**
77+
* Convert the resource instance into JSON.
78+
*/
79+
public function toJson(int $options = 0): string
80+
{
81+
$json = json_encode($this->jsonSerialize(), $options);
82+
83+
return $json;
84+
}
85+
86+
/**
87+
* Convert the object into something JSON serializable.
88+
*/
89+
public function jsonSerialize(): mixed
90+
{
91+
return $this->toArray();
92+
}
93+
94+
/**
95+
* Dynamically retrieve attributes on the resource.
96+
*/
97+
public function __get($name)
98+
{
99+
return $this->getAttribute($name);
100+
}
101+
102+
/**
103+
* Get all the attributes when dumping the resource.
104+
*/
105+
public function __debugInfo(): array
106+
{
107+
return $this->getAttributes();
108+
}
109+
110+
public function offsetExists(mixed $offset): bool
111+
{
112+
try {
113+
return ! is_null($this->getAttribute($offset));
114+
} catch (MissingAttributeException) {
115+
return false;
116+
}
117+
}
118+
119+
public function offsetGet(mixed $offset): mixed
120+
{
121+
return $this->getAttribute($offset);
122+
}
123+
124+
public function offsetSet(mixed $offset, mixed $value): void
125+
{
126+
throw new BadMethodCallException('Cannot set resource attributes.');
127+
}
128+
129+
public function offsetUnset(mixed $offset): void
130+
{
131+
throw new BadMethodCallException('Cannot unset resource attributes.');
132+
}
133+
}

0 commit comments

Comments
 (0)