From 58c164711ca7f6a8c93f5cdc68cf14b6cce59777 Mon Sep 17 00:00:00 2001 From: Roman Lytvynenko Date: Mon, 11 Mar 2024 21:20:51 +0200 Subject: [PATCH] fixed carbon being string in open api --- .../JsonResourceTypeToSchema.php | 15 +++++++++ tests/TypeToSchemaTransformerTest.php | 31 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/Support/TypeToSchemaExtensions/JsonResourceTypeToSchema.php b/src/Support/TypeToSchemaExtensions/JsonResourceTypeToSchema.php index c83f407e..2abdd529 100644 --- a/src/Support/TypeToSchemaExtensions/JsonResourceTypeToSchema.php +++ b/src/Support/TypeToSchemaExtensions/JsonResourceTypeToSchema.php @@ -2,6 +2,7 @@ namespace Dedoc\Scramble\Support\TypeToSchemaExtensions; +use Carbon\Carbon; use Dedoc\Scramble\Extensions\TypeToSchemaExtension; use Dedoc\Scramble\Support\Generator\Reference; use Dedoc\Scramble\Support\Generator\Response; @@ -14,6 +15,7 @@ use Dedoc\Scramble\Support\Type\Generic; use Dedoc\Scramble\Support\Type\Literal\LiteralBooleanType; use Dedoc\Scramble\Support\Type\ObjectType; +use Dedoc\Scramble\Support\Type\StringType; use Dedoc\Scramble\Support\Type\Type; use Dedoc\Scramble\Support\Type\TypeWalker; use Dedoc\Scramble\Support\Type\Union; @@ -70,6 +72,19 @@ private function flattenMergeValues(array $items) return [$item]; } + if ( + $item->value instanceof Union + && (new TypeWalker)->first($item->value, fn (Type $t) => $t->isInstanceOf(Carbon::class)) + ) { + (new TypeWalker)->replace($item->value, function (Type $t) { + return $t->isInstanceOf(Carbon::class) + ? tap(new StringType, fn ($t) => $t->setAttribute('format', 'date-time')) + : null; + }); + + return [$item]; + } + if ($item->value->isInstanceOf(JsonResource::class)) { $resource = $this->getResourceType($item->value); diff --git a/tests/TypeToSchemaTransformerTest.php b/tests/TypeToSchemaTransformerTest.php index c14d1182..fcca9dbc 100644 --- a/tests/TypeToSchemaTransformerTest.php +++ b/tests/TypeToSchemaTransformerTest.php @@ -15,6 +15,7 @@ use Dedoc\Scramble\Support\TypeToSchemaExtensions\AnonymousResourceCollectionTypeToSchema; use Dedoc\Scramble\Support\TypeToSchemaExtensions\EnumToSchema; use Dedoc\Scramble\Support\TypeToSchemaExtensions\JsonResourceTypeToSchema; +use Dedoc\Scramble\Tests\Files\SamplePostModel; use Illuminate\Http\Resources\Json\JsonResource; use function Spatie\Snapshots\assertMatchesSnapshot; @@ -132,6 +133,21 @@ ]); }); +it('infers date column directly referenced in json as date-time', function () { + $transformer = new TypeTransformer($infer = app(Infer::class), $components = new Components, [JsonResourceTypeToSchema::class]); + + $type = new ObjectType(InferTypesTest_JsonResourceWithCarbonAttribute::class); + + expect($transformer->transform($type)->toArray())->toBe([ + '$ref' => '#/components/schemas/InferTypesTest_JsonResourceWithCarbonAttribute', + ]); + + expect($components->getSchema(InferTypesTest_JsonResourceWithCarbonAttribute::class)->toArray()['properties']['created_at'])->toBe([ + 'type' => ['string', 'null'], + 'format' => 'date-time', + ]); +}); + class ComplexTypeHandlersTest_SampleType extends JsonResource { public function toArray($request) @@ -220,6 +236,21 @@ public function toArray($request) } } +/** + * @property SamplePostModel $resource + */ +class InferTypesTest_JsonResourceWithCarbonAttribute extends JsonResource +{ + public function toArray($request) + { + return [ + 'id' => $this->id, + 'created_at' => $this->created_at, + 'updated_at' => $this->updated_at, + ]; + } +} + enum StatusTwo: string { case DRAFT = 'draft';