From 7f935ebe4c731da5217918918b3f68e0ec95b529 Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 15:16:25 +0545 Subject: [PATCH 01/17] test: updates invalid API URL in UploadTest for network error handling --- tests/UploadTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/UploadTest.php b/tests/UploadTest.php index d627cf8..8b690ce 100644 --- a/tests/UploadTest.php +++ b/tests/UploadTest.php @@ -129,14 +129,14 @@ }); it('throws network error when Guzzle cannot connect to server. (GET)', function () { - $client = new HamroCDN('test-api-key', 'https://hamrocdn123.com/invalid-api'); + $client = new HamroCDN('test-api-key', 'https://hamrocdn.com/invalid-api'); $this->expectException(HamroCDNException::class); $client->index(); }); it('throws network error when Guzzle cannot connect to server. (POST)', function () { - $client = new HamroCDN('test-api-key', 'https://hamrocdn123.com/invalid-api'); + $client = new HamroCDN('test-api-key', 'https://hamrocdn.com/invalid-api'); $filePath = __DIR__.'/test.png'; From 557dc82da5a00f6c7dc96a145791aea9d1b73ad4 Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 20:04:53 +0545 Subject: [PATCH 02/17] chore: adds nesbot/carbon dependency to composer.json --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5e78058..bca6ba6 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,8 @@ ], "require": { "php": ">=8.0", - "guzzlehttp/guzzle": "^7.10" + "guzzlehttp/guzzle": "^7.10", + "nesbot/carbon": "^3.10" }, "require-dev": { "laravel/pint": "^1.25", From 6fe856e9959ba3f53199c575467cb7b05f14590a Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 20:05:10 +0545 Subject: [PATCH 03/17] feat: adds User model for user data management --- src/Models/User.php | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/Models/User.php diff --git a/src/Models/User.php b/src/Models/User.php new file mode 100644 index 0000000..dd7a004 --- /dev/null +++ b/src/Models/User.php @@ -0,0 +1,35 @@ +name = $name; + $this->email = $email; + } + + public function getName(): string + { + return $this->name; + } + + public function getEmail(): string + { + return $this->email; + } + + public function toArray(): array + { + return [ + 'name' => $this->name, + 'email' => $this->email, + ]; + } +} From c205b474244e70e4ac0ca40a6eca290cbb9c3fdd Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 20:07:06 +0545 Subject: [PATCH 04/17] feat: adds File model for file data management --- src/Models/File.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/Models/File.php diff --git a/src/Models/File.php b/src/Models/File.php new file mode 100644 index 0000000..736d86d --- /dev/null +++ b/src/Models/File.php @@ -0,0 +1,36 @@ +url = $url; + $this->size = $size; + } + + public function getUrl(): string + { + return $this->url; + } + + public function getSize(): int + { + return $this->size; + } + + public function toArray(): array + { + return [ + 'url' => $this->url, + 'size' => $this->size, + ]; + } +} From 12a3fa883c299db8595a956da321d4da87547e4e Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 20:08:41 +0545 Subject: [PATCH 05/17] feat: adds Upload model --- src/Models/Upload.php | 51 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/Models/Upload.php diff --git a/src/Models/Upload.php b/src/Models/Upload.php new file mode 100644 index 0000000..45993af --- /dev/null +++ b/src/Models/Upload.php @@ -0,0 +1,51 @@ +nanoId = $nanoId; + $this->user = $user; + $this->deleteAt = $deleteAt; + $this->original = $original; + } + + public function getNanoId(): string + { + return $this->nanoId; + } + + public function getUser(): ?User + { + return $this->user; + } + + public function getDeleteAt(): ?string + { + return $this->deleteAt; + } + + public function getOriginal(): File + { + return $this->original; + } + + public function toArray(): array + { + return [ + 'nanoId' => $this->nanoId, + 'user' => $this->user?->toArray(), + 'delete_at' => $this->deleteAt, + 'original' => $this->original->toArray(), + ]; + } +} From a657068523f5b3e52b94bfa326227857c90b8af1 Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 21:54:51 +0545 Subject: [PATCH 06/17] feat: adds PHPStan types and fromArray methods for File, User, and Upload models Enhances type safety and data handling in the models. --- src/Contracts/HamroCDNContract.php | 19 ++++--------------- src/Models/File.php | 15 +++++++++++++++ src/Models/Upload.php | 11 +++++++++++ src/Models/User.php | 17 +++++++++++++++++ 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/Contracts/HamroCDNContract.php b/src/Contracts/HamroCDNContract.php index 53a1917..a9113b9 100644 --- a/src/Contracts/HamroCDNContract.php +++ b/src/Contracts/HamroCDNContract.php @@ -4,22 +4,11 @@ namespace HamroCDN\Contracts; +use HamroCDN\Models\Upload; + /** - * @phpstan-type HamroCDNFile array{ - * url: string, - * size: int - * } - * @phpstan-type HamroCDNUser array{ - * name: string, - * email: string, - * role: string - * } - * @phpstan-type HamroCDNObject array{ - * nanoId: string, - * user: HamroCDNUser, - * delete_at: string|null, - * original: HamroCDNFile - * } + * @phpstan-import-type HamroCDNObject from Upload + * * @phpstan-type HamroCDNData array{ * data: HamroCDNObject * } diff --git a/src/Models/File.php b/src/Models/File.php index 736d86d..92c7fba 100644 --- a/src/Models/File.php +++ b/src/Models/File.php @@ -4,6 +4,12 @@ namespace HamroCDN\Models; +/** + * @phpstan-type HamroCDNFile array{ + * url: string, + * size: int + * } + */ final class File { private string $url; @@ -33,4 +39,13 @@ public function toArray(): array 'size' => $this->size, ]; } + + /** @param HamroCDNFile $data */ + public static function fromArray(array $data): self + { + return new self( + $data['url'] ?? '', + (int) ($data['size'] ?? 0), + ); + } } diff --git a/src/Models/Upload.php b/src/Models/Upload.php index 45993af..559c464 100644 --- a/src/Models/Upload.php +++ b/src/Models/Upload.php @@ -4,6 +4,17 @@ namespace HamroCDN\Models; +/** + * @phpstan-import-type HamroCDNUser from User + * @phpstan-import-type HamroCDNFile from File + * + * @phpstan-type HamroCDNObject array{ + * nanoId: string, + * user: HamroCDNUser, + * delete_at: string|null, + * original: HamroCDNFile + * } + */ final class Upload { private string $nanoId; diff --git a/src/Models/User.php b/src/Models/User.php index dd7a004..3efd69a 100644 --- a/src/Models/User.php +++ b/src/Models/User.php @@ -4,6 +4,12 @@ namespace HamroCDN\Models; +/** + * @phpstan-type HamroCDNUser array{ + * name: string, + * email: string + * } + */ final class User { private string $name; @@ -32,4 +38,15 @@ public function toArray(): array 'email' => $this->email, ]; } + + /** + * @param HamroCDNUser $data + */ + public static function fromArray(array $data): self + { + return new self( + $data['name'] ?? '', + $data['email'] ?? '', + ); + } } From f7cedade6e84ed95297eaa889b085ab4b6f1daf8 Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 21:59:13 +0545 Subject: [PATCH 07/17] feat: adds return type hints for toArray methods in File, User, and Upload models --- src/Models/File.php | 5 +++-- src/Models/Upload.php | 3 ++- src/Models/User.php | 9 ++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Models/File.php b/src/Models/File.php index 92c7fba..6e133af 100644 --- a/src/Models/File.php +++ b/src/Models/File.php @@ -32,6 +32,7 @@ public function getSize(): int return $this->size; } + /** @return HamroCDNFile */ public function toArray(): array { return [ @@ -44,8 +45,8 @@ public function toArray(): array public static function fromArray(array $data): self { return new self( - $data['url'] ?? '', - (int) ($data['size'] ?? 0), + $data['url'], + (int) $data['size'], ); } } diff --git a/src/Models/Upload.php b/src/Models/Upload.php index 559c464..8e3ddec 100644 --- a/src/Models/Upload.php +++ b/src/Models/Upload.php @@ -10,7 +10,7 @@ * * @phpstan-type HamroCDNObject array{ * nanoId: string, - * user: HamroCDNUser, + * user: HamroCDNUser|null, * delete_at: string|null, * original: HamroCDNFile * } @@ -50,6 +50,7 @@ public function getOriginal(): File return $this->original; } + /** @return HamroCDNObject */ public function toArray(): array { return [ diff --git a/src/Models/User.php b/src/Models/User.php index 3efd69a..2d6aff4 100644 --- a/src/Models/User.php +++ b/src/Models/User.php @@ -31,6 +31,7 @@ public function getEmail(): string return $this->email; } + /** @return HamroCDNUser */ public function toArray(): array { return [ @@ -39,14 +40,12 @@ public function toArray(): array ]; } - /** - * @param HamroCDNUser $data - */ + /** @param HamroCDNUser $data */ public static function fromArray(array $data): self { return new self( - $data['name'] ?? '', - $data['email'] ?? '', + $data['name'], + $data['email'], ); } } From e38a57eb6d59e98dfa0f5834e5e6c4e6dd7dfd28 Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 22:17:30 +0545 Subject: [PATCH 08/17] feat: refactors constructors in models --- src/Models/File.php | 25 ++++++++++--------------- src/Models/Upload.php | 18 ++++++------------ src/Models/User.php | 24 ++++++++++-------------- 3 files changed, 26 insertions(+), 41 deletions(-) diff --git a/src/Models/File.php b/src/Models/File.php index 6e133af..25ba481 100644 --- a/src/Models/File.php +++ b/src/Models/File.php @@ -12,14 +12,18 @@ */ final class File { - private string $url; + public function __construct( + private string $url, + private int $size + ) {} - private int $size; - - public function __construct(string $url, int $size) + /** @param HamroCDNFile $data */ + public static function fromArray(array $data): self { - $this->url = $url; - $this->size = $size; + return new self( + $data['url'], + (int) $data['size'], + ); } public function getUrl(): string @@ -40,13 +44,4 @@ public function toArray(): array 'size' => $this->size, ]; } - - /** @param HamroCDNFile $data */ - public static function fromArray(array $data): self - { - return new self( - $data['url'], - (int) $data['size'], - ); - } } diff --git a/src/Models/Upload.php b/src/Models/Upload.php index 8e3ddec..b5e92cb 100644 --- a/src/Models/Upload.php +++ b/src/Models/Upload.php @@ -17,18 +17,12 @@ */ final class Upload { - private string $nanoId; - private ?User $user; - private ?string $deleteAt; - private File $original; - - public function __construct(string $nanoId, ?User $user, ?string $deleteAt, File $original) - { - $this->nanoId = $nanoId; - $this->user = $user; - $this->deleteAt = $deleteAt; - $this->original = $original; - } + public function __construct( + private string $nanoId, + private ?User $user, + private ?string $deleteAt, + private File $original + ) {} public function getNanoId(): string { diff --git a/src/Models/User.php b/src/Models/User.php index 2d6aff4..f22b399 100644 --- a/src/Models/User.php +++ b/src/Models/User.php @@ -12,13 +12,18 @@ */ final class User { - private string $name; - private string $email; + public function __construct( + private string $name, + private string $email + ) {} - public function __construct(string $name, string $email) + /** @param HamroCDNUser $data */ + public static function fromArray(array $data): self { - $this->name = $name; - $this->email = $email; + return new self( + $data['name'], + $data['email'], + ); } public function getName(): string @@ -39,13 +44,4 @@ public function toArray(): array 'email' => $this->email, ]; } - - /** @param HamroCDNUser $data */ - public static function fromArray(array $data): self - { - return new self( - $data['name'], - $data['email'], - ); - } } From 4a2369988b35cbfb0fddbb1a1fdec4e65e7f406e Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 22:21:37 +0545 Subject: [PATCH 09/17] feat: updates return types for fetch, upload, and uploadByURL methods --- src/Contracts/HamroCDNContract.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Contracts/HamroCDNContract.php b/src/Contracts/HamroCDNContract.php index a9113b9..3b3688d 100644 --- a/src/Contracts/HamroCDNContract.php +++ b/src/Contracts/HamroCDNContract.php @@ -29,21 +29,17 @@ public function index(): array; /** * Fetch a file from HamroCDN. * - * @return HamroCDNData + * @return array */ public function fetch(string $nanoId): array; /** * Upload a file to HamroCDN. - * - * @return HamroCDNData */ - public function upload(string $filePath): array; + public function upload(string $filePath): Upload; /** * Upload a file to HamroCDN by URL. - * - * @return HamroCDNData */ - public function uploadByURL(string $url): array; + public function uploadByURL(string $url): Upload; } From 07c3b3489b0e9cc426eda17da5b4ff9b388f28a3 Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 22:26:51 +0545 Subject: [PATCH 10/17] refactor: updates type hints --- src/Contracts/HamroCDNContract.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Contracts/HamroCDNContract.php b/src/Contracts/HamroCDNContract.php index 3b3688d..c575504 100644 --- a/src/Contracts/HamroCDNContract.php +++ b/src/Contracts/HamroCDNContract.php @@ -10,10 +10,10 @@ * @phpstan-import-type HamroCDNObject from Upload * * @phpstan-type HamroCDNData array{ - * data: HamroCDNObject + * data: Upload * } * @phpstan-type HamroCDNObjectWithPagination array{ - * data: array, + * data: array, * meta: array{total: int, per_page: int, page: int} * } */ @@ -29,7 +29,7 @@ public function index(): array; /** * Fetch a file from HamroCDN. * - * @return array + * @return HamroCDNData */ public function fetch(string $nanoId): array; From 78c6d181d9a3b30f245403845d48c7de7166e735 Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 22:34:23 +0545 Subject: [PATCH 11/17] feat: updates return types for methods Enhances type safety by returning Upload objects instead of arrays. --- src/Contracts/HamroCDNContract.php | 8 +++---- src/HamroCDN.php | 36 +++++++++++++++++++++--------- src/Models/Upload.php | 18 +++++++++++++++ 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/Contracts/HamroCDNContract.php b/src/Contracts/HamroCDNContract.php index c575504..4e7a3fe 100644 --- a/src/Contracts/HamroCDNContract.php +++ b/src/Contracts/HamroCDNContract.php @@ -10,10 +10,10 @@ * @phpstan-import-type HamroCDNObject from Upload * * @phpstan-type HamroCDNData array{ - * data: Upload + * data: HamroCDNObject * } * @phpstan-type HamroCDNObjectWithPagination array{ - * data: array, + * data: array, * meta: array{total: int, per_page: int, page: int} * } */ @@ -28,10 +28,8 @@ public function index(): array; /** * Fetch a file from HamroCDN. - * - * @return HamroCDNData */ - public function fetch(string $nanoId): array; + public function fetch(string $nanoId): Upload; /** * Upload a file to HamroCDN. diff --git a/src/HamroCDN.php b/src/HamroCDN.php index a5f59a6..3fc8b3f 100644 --- a/src/HamroCDN.php +++ b/src/HamroCDN.php @@ -7,12 +7,12 @@ use GuzzleHttp\Client; use HamroCDN\Contracts\HamroCDNContract; use HamroCDN\Exceptions\HamroCDNException; +use HamroCDN\Models\Upload; use HamroCDN\Traits\HasConfigValues; use HamroCDN\Traits\Requestable; /** * @phpstan-import-type HamroCDNData from HamroCDNContract - * @phpstan-import-type HamroCDNObjectWithPagination from HamroCDNContract */ final class HamroCDN implements HamroCDNContract { @@ -37,37 +37,45 @@ public function __construct(?string $apiKey = null, ?string $baseUrl = null, ?Cl } /** - * @return HamroCDNObjectWithPagination - * * @throws HamroCDNException */ public function index(?int $per_page = 20, ?int $page = 1): array { - /** @var HamroCDNObjectWithPagination */ - return $this->get('uploads', [ + $response = $this->get('uploads', [ 'per_page' => $per_page, 'page' => $page, ]); + + $data = $response['data'] ?? []; + $meta = $response['meta'] ?? ['total' => 0, 'per_page' => $per_page, 'page' => $page]; + + return [ + 'data' => array_map(fn ($item) => Upload::fromArray($item), $data), + 'meta' => $meta, + ]; } /** * @throws HamroCDNException */ - public function fetch(string $nanoId): array + public function fetch(string $nanoId): Upload { - return $this->get("uploads/{$nanoId}"); + $response = $this->get("uploads/{$nanoId}"); + $data = $response['data'] ?? []; + + return Upload::fromArray($data); } /** * @throws HamroCDNException */ - public function upload(string $filePath): array + public function upload(string $filePath): Upload { if (! file_exists($filePath)) { throw HamroCDNException::fileError($filePath); } - return $this->post('uploads', [ + $response = $this->post('uploads', [ 'multipart' => [ [ 'name' => 'file', @@ -76,17 +84,23 @@ public function upload(string $filePath): array ], ], ]); + + $data = $response['data'] ?? []; + return Upload::fromArray($data); } /** * @throws HamroCDNException */ - public function uploadByURL(string $url): array + public function uploadByURL(string $url): Upload { - return $this->post('upload-from-url', [ + $response = $this->post('upload-from-url', [ 'json' => [ 'url' => $url, ], ]); + + $data = $response['data'] ?? []; + return Upload::fromArray($data); } } diff --git a/src/Models/Upload.php b/src/Models/Upload.php index b5e92cb..ec4ffb5 100644 --- a/src/Models/Upload.php +++ b/src/Models/Upload.php @@ -54,4 +54,22 @@ public function toArray(): array 'original' => $this->original->toArray(), ]; } + + /** @param HamroCDNObject $data */ + public static function fromArray(array $data): self + { + $user = null; + if (isset($data['user'])) { + $user = User::fromArray($data['user']); + } + + $original = File::fromArray($data['original']); + + return new self( + $data['nanoId'], + $user, + $data['delete_at'] ?? null, + $original + ); + } } From eac40427179fd0c14d84d4b4493060caf3f7c995 Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 22:36:20 +0545 Subject: [PATCH 12/17] refactor: refactors data mapping --- src/HamroCDN.php | 9 ++++++++- src/Models/Upload.php | 36 ++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/HamroCDN.php b/src/HamroCDN.php index 3fc8b3f..1a37551 100644 --- a/src/HamroCDN.php +++ b/src/HamroCDN.php @@ -49,8 +49,13 @@ public function index(?int $per_page = 20, ?int $page = 1): array $data = $response['data'] ?? []; $meta = $response['meta'] ?? ['total' => 0, 'per_page' => $per_page, 'page' => $page]; + $uploads = array_map( + fn (array|string|null $item): Upload => Upload::fromArray($item), + $data + ); + return [ - 'data' => array_map(fn ($item) => Upload::fromArray($item), $data), + 'data' => $uploads, 'meta' => $meta, ]; } @@ -86,6 +91,7 @@ public function upload(string $filePath): Upload ]); $data = $response['data'] ?? []; + return Upload::fromArray($data); } @@ -101,6 +107,7 @@ public function uploadByURL(string $url): Upload ]); $data = $response['data'] ?? []; + return Upload::fromArray($data); } } diff --git a/src/Models/Upload.php b/src/Models/Upload.php index ec4ffb5..5b19627 100644 --- a/src/Models/Upload.php +++ b/src/Models/Upload.php @@ -24,6 +24,24 @@ public function __construct( private File $original ) {} + /** @param HamroCDNObject $data */ + public static function fromArray(array $data): self + { + $user = null; + if (isset($data['user'])) { + $user = User::fromArray($data['user']); + } + + $original = File::fromArray($data['original']); + + return new self( + $data['nanoId'], + $user, + $data['delete_at'] ?? null, + $original + ); + } + public function getNanoId(): string { return $this->nanoId; @@ -54,22 +72,4 @@ public function toArray(): array 'original' => $this->original->toArray(), ]; } - - /** @param HamroCDNObject $data */ - public static function fromArray(array $data): self - { - $user = null; - if (isset($data['user'])) { - $user = User::fromArray($data['user']); - } - - $original = File::fromArray($data['original']); - - return new self( - $data['nanoId'], - $user, - $data['delete_at'] ?? null, - $original - ); - } } From e986d018013636bcf6d959811f8ff2acd106cdbd Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 22:45:23 +0545 Subject: [PATCH 13/17] refactor: updates type hints and response handling in methods --- src/Contracts/HamroCDNContract.php | 3 ++- src/HamroCDN.php | 30 ++++++++++++------------------ src/Models/Upload.php | 4 ++++ 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/Contracts/HamroCDNContract.php b/src/Contracts/HamroCDNContract.php index 4e7a3fe..a8609e1 100644 --- a/src/Contracts/HamroCDNContract.php +++ b/src/Contracts/HamroCDNContract.php @@ -8,6 +8,7 @@ /** * @phpstan-import-type HamroCDNObject from Upload + * @phpstan-import-type UploadWithPagination from Upload * * @phpstan-type HamroCDNData array{ * data: HamroCDNObject @@ -22,7 +23,7 @@ interface HamroCDNContract /** * List all of your files in HamroCDN. * - * @return HamroCDNObjectWithPagination + * @return UploadWithPagination */ public function index(): array; diff --git a/src/HamroCDN.php b/src/HamroCDN.php index 1a37551..048477c 100644 --- a/src/HamroCDN.php +++ b/src/HamroCDN.php @@ -12,7 +12,9 @@ use HamroCDN\Traits\Requestable; /** + * @phpstan-import-type HamroCDNObject from Upload * @phpstan-import-type HamroCDNData from HamroCDNContract + * @phpstan-import-type HamroCDNObjectWithPagination from HamroCDNContract */ final class HamroCDN implements HamroCDNContract { @@ -41,22 +43,19 @@ public function __construct(?string $apiKey = null, ?string $baseUrl = null, ?Cl */ public function index(?int $per_page = 20, ?int $page = 1): array { + /** @var HamroCDNObjectWithPagination $response */ $response = $this->get('uploads', [ 'per_page' => $per_page, 'page' => $page, ]); - $data = $response['data'] ?? []; - $meta = $response['meta'] ?? ['total' => 0, 'per_page' => $per_page, 'page' => $page]; - - $uploads = array_map( - fn (array|string|null $item): Upload => Upload::fromArray($item), - $data - ); - return [ - 'data' => $uploads, - 'meta' => $meta, + 'data' => array_map( + /** @param HamroCDNObject $item */ + fn (array $item): Upload => Upload::fromArray($item), + $response['data'] + ), + 'meta' => $response['meta'], ]; } @@ -66,9 +65,8 @@ public function index(?int $per_page = 20, ?int $page = 1): array public function fetch(string $nanoId): Upload { $response = $this->get("uploads/{$nanoId}"); - $data = $response['data'] ?? []; - return Upload::fromArray($data); + return Upload::fromArray($response['data']); } /** @@ -90,9 +88,7 @@ public function upload(string $filePath): Upload ], ]); - $data = $response['data'] ?? []; - - return Upload::fromArray($data); + return Upload::fromArray($response['data']); } /** @@ -106,8 +102,6 @@ public function uploadByURL(string $url): Upload ], ]); - $data = $response['data'] ?? []; - - return Upload::fromArray($data); + return Upload::fromArray($response['data']); } } diff --git a/src/Models/Upload.php b/src/Models/Upload.php index 5b19627..1ce61c0 100644 --- a/src/Models/Upload.php +++ b/src/Models/Upload.php @@ -14,6 +14,10 @@ * delete_at: string|null, * original: HamroCDNFile * } + * @phpstan-type UploadWithPagination array{ + * data: array, + * meta: array{total: int, per_page: int, page: int} + * } */ final class Upload { From dc52b4f2fd11a307415a1d094714ed3b8aee931d Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 22:59:18 +0545 Subject: [PATCH 14/17] test: adds custom expectation for Upload object validation --- tests/UploadTest.php | 76 +++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 43 deletions(-) diff --git a/tests/UploadTest.php b/tests/UploadTest.php index 8b690ce..3748f3a 100644 --- a/tests/UploadTest.php +++ b/tests/UploadTest.php @@ -4,6 +4,26 @@ use HamroCDN\Exceptions\HamroCDNException; use HamroCDN\HamroCDN; +use HamroCDN\Models\Upload; +use HamroCDN\Models\User; + +expect()->extend('toBeUploadObject', function () { + expect($this->value) + ->toBeInstanceOf(Upload::class); + + expect($this->value) + ->toHaveKey('nanoId') + ->toHaveKey('user') + ->toHaveKey('delete_at') + ->toHaveKey('original'); + + expect($this->value->getOriginal()) + ->toHaveKey('url') + ->toHaveKey('size'); + + expect($this->value->getUser()) + ->toBeInstanceOf(User::class); +}); it('returns an array of HamroCDN objects from index', function () { $client = new HamroCDN('test-api-key', 'https://hamrocdn.com/api'); @@ -15,22 +35,14 @@ ->toHaveKey('data') ->toHaveKey('meta'); - foreach ($uploads['data'] as $upload) { - expect($upload) - ->toHaveKey('nanoId') - ->toHaveKey('user') - ->toHaveKey('delete_at') - ->toHaveKey('original'); - - expect($upload['original']) - ->toHaveKey('url') - ->toHaveKey('size'); - } - expect($uploads['meta']) ->toHaveKey('total') ->toHaveKey('per_page') ->toHaveKey('page'); + + foreach ($uploads['data'] as $upload) { + expect($upload)->toBeUploadObject(); + } }); it('uploads a file and returns a HamroCDN object', function () { @@ -38,24 +50,15 @@ $filePath = __DIR__.'/test.png'; $upload = $client->upload($filePath); - $data = $upload['data']; - expect($data) - ->toHaveKey('nanoId') - ->toHaveKey('user') - ->toHaveKey('delete_at') - ->toHaveKey('original'); + expect($upload)->toBeUploadObject(); - $fetchResponse = $client->fetch($data['nanoId']); - $fetchedData = $fetchResponse['data']; + $fetchedUpload = $client->fetch($upload->getNanoId()); - expect($fetchedData) - ->toHaveKey('nanoId') - ->toHaveKey('user') - ->toHaveKey('delete_at') - ->toHaveKey('original'); + expect($fetchedUpload) + ->toBeUploadObject(); - expect($fetchedData['nanoId'])->toBe($data['nanoId']); + expect($fetchedUpload->getNanoId())->toBe($upload->getNanoId()); }); it('uploads a file by URL and returns a HamroCDN object', function () { @@ -64,24 +67,11 @@ $fileUrl = 'https://placehold.co/1000x1000/000000/FFFFFF?text=HamroCDN'; $upload = $client->uploadByURL($fileUrl); - $data = $upload['data']; - - expect($data) - ->toHaveKey('nanoId') - ->toHaveKey('user') - ->toHaveKey('delete_at') - ->toHaveKey('original'); - - $fetchResponse = $client->fetch($data['nanoId']); - $fetchedData = $fetchResponse['data']; - - expect($fetchedData) - ->toHaveKey('nanoId') - ->toHaveKey('user') - ->toHaveKey('delete_at') - ->toHaveKey('original'); + expect($upload)->toBeUploadObject(); - expect($fetchedData['nanoId'])->toBe($data['nanoId']); + $fetchedUpload = $client->fetch($upload->getNanoId()); + expect($fetchedUpload) + ->toBeUploadObject(); }); describe('exception', function () { From 2a4c4a5035022d7ecabdca1de9a323e89ad0e04c Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 23:00:21 +0545 Subject: [PATCH 15/17] test: type hinting added --- tests/UploadTest.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/UploadTest.php b/tests/UploadTest.php index 3748f3a..3ae6194 100644 --- a/tests/UploadTest.php +++ b/tests/UploadTest.php @@ -8,20 +8,23 @@ use HamroCDN\Models\User; expect()->extend('toBeUploadObject', function () { - expect($this->value) + /** @var Upload $upload */ + $upload = $this->value; + + expect($upload) ->toBeInstanceOf(Upload::class); - expect($this->value) + expect($upload) ->toHaveKey('nanoId') ->toHaveKey('user') ->toHaveKey('delete_at') ->toHaveKey('original'); - expect($this->value->getOriginal()) + expect($upload->getOriginal()) ->toHaveKey('url') ->toHaveKey('size'); - expect($this->value->getUser()) + expect($upload->getUser()) ->toBeInstanceOf(User::class); }); From 350de5861e1bcccb2c15d731c669b34f7e2d4e56 Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 23:04:27 +0545 Subject: [PATCH 16/17] test: adds unit test for Upload model data validation --- tests/UploadTest.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/UploadTest.php b/tests/UploadTest.php index 3ae6194..035f6cf 100644 --- a/tests/UploadTest.php +++ b/tests/UploadTest.php @@ -28,6 +28,32 @@ ->toBeInstanceOf(User::class); }); +it('checks the dummy data to have correct value in model', function () { + $dummyData = [ + 'nanoId' => 'abc123', + 'user' => [ + 'name' => 'John Doe', + 'email' => 'john@hamrocdn.com', + ], + 'delete_at' => null, + 'original' => [ + 'url' => 'https://hamrocdn.com/abc123.png', + 'size' => 2048, + ], + ]; + + $upload = Upload::fromArray($dummyData); + + expect($upload)->toBeUploadObject(); + + expect($upload->getNanoId())->toBe('abc123'); + expect($upload->getDeleteAt())->toBeNull(); + expect($upload->getOriginal()->getUrl())->toBe('https://hamrocdn.com/abc123.png'); + expect($upload->getOriginal()->getSize())->toBe(2048); + expect($upload->getUser()?->getName())->toBe('John Doe'); + expect($upload->getUser()?->getEmail())->toBe('john@hamrocdn.com'); +}); + it('returns an array of HamroCDN objects from index', function () { $client = new HamroCDN('test-api-key', 'https://hamrocdn.com/api'); From de5c8454293b05332b4242f8e0b5014118eaa76a Mon Sep 17 00:00:00 2001 From: achyutkneupane Date: Tue, 28 Oct 2025 23:08:08 +0545 Subject: [PATCH 17/17] refactor: updates delete_at property to Carbon --- src/Models/Upload.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Models/Upload.php b/src/Models/Upload.php index 1ce61c0..1107f98 100644 --- a/src/Models/Upload.php +++ b/src/Models/Upload.php @@ -4,6 +4,8 @@ namespace HamroCDN\Models; +use Carbon\Carbon; + /** * @phpstan-import-type HamroCDNUser from User * @phpstan-import-type HamroCDNFile from File @@ -11,7 +13,7 @@ * @phpstan-type HamroCDNObject array{ * nanoId: string, * user: HamroCDNUser|null, - * delete_at: string|null, + * delete_at: string|Carbon|null, * original: HamroCDNFile * } * @phpstan-type UploadWithPagination array{ @@ -24,7 +26,7 @@ final class Upload public function __construct( private string $nanoId, private ?User $user, - private ?string $deleteAt, + private ?Carbon $deleteAt, private File $original ) {} @@ -41,7 +43,7 @@ public static function fromArray(array $data): self return new self( $data['nanoId'], $user, - $data['delete_at'] ?? null, + isset($data['delete_at']) ? new Carbon($data['delete_at']) : null, $original ); } @@ -56,7 +58,7 @@ public function getUser(): ?User return $this->user; } - public function getDeleteAt(): ?string + public function getDeleteAt(): ?Carbon { return $this->deleteAt; }