diff --git a/composer.json b/composer.json index 58597a3..5135232 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ "require": { "php": ">=8.1", "psx/json": "^3.0", - "psx/openapi": "^0.1", + "psx/openapi": "^1.0", "psx/schema": "^7.0", "symfony/cache": "^5.0|^6.0|^7.0", "symfony/console": "^5.0|^6.0|^7.0", diff --git a/src/Attribute/ParamAbstract.php b/src/Attribute/ParamAbstract.php index 4006540..e050f23 100644 --- a/src/Attribute/ParamAbstract.php +++ b/src/Attribute/ParamAbstract.php @@ -34,14 +34,7 @@ public function __construct( public string $name, public Type $type, public ?string $description = null, - public ?bool $required = null, - public ?array $enum = null, - public ?int $minLength = null, - public ?int $maxLength = null, - public ?string $pattern = null, public ?Format $format = null, - public ?int $minimum = null, - public ?int $maximum = null ) { } diff --git a/src/Builder/SpecificationBuilder.php b/src/Builder/SpecificationBuilder.php index 2157aa5..12c69e3 100644 --- a/src/Builder/SpecificationBuilder.php +++ b/src/Builder/SpecificationBuilder.php @@ -26,6 +26,8 @@ use PSX\Api\SpecificationInterface; use PSX\Schema\ContentType; use PSX\Schema\DefinitionsInterface; +use PSX\Schema\Type\DefinitionTypeAbstract; +use PSX\Schema\Type\PropertyTypeAbstract; use PSX\Schema\TypeInterface; /** @@ -54,7 +56,7 @@ public function setSecurity(SecurityInterface $security): void $this->specification->setSecurity($security); } - public function addOperation(string $operationId, string $method, string $path, int $statusCode, TypeInterface|ContentType $schema): OperationBuilderInterface + public function addOperation(string $operationId, string $method, string $path, int $statusCode, PropertyTypeAbstract|ContentType $schema): OperationBuilderInterface { if ($this->specification->getOperations()->has($operationId)) { throw new OperationAlreadyExistsException('Operation "' . $operationId . '" already exists'); @@ -71,7 +73,7 @@ public function addDefinitions(DefinitionsInterface $definitions): self return $this; } - public function addType(string $name, TypeInterface $schema): self + public function addType(string $name, DefinitionTypeAbstract $schema): self { $this->specification->getDefinitions()->addType($name, $schema); return $this; diff --git a/src/Builder/SpecificationBuilderInterface.php b/src/Builder/SpecificationBuilderInterface.php index 261d096..d978050 100644 --- a/src/Builder/SpecificationBuilderInterface.php +++ b/src/Builder/SpecificationBuilderInterface.php @@ -24,7 +24,8 @@ use PSX\Api\SpecificationInterface; use PSX\Schema\ContentType; use PSX\Schema\DefinitionsInterface; -use PSX\Schema\TypeInterface; +use PSX\Schema\Type\DefinitionTypeAbstract; +use PSX\Schema\Type\PropertyTypeAbstract; /** * SpecificationBuilderInterface @@ -39,11 +40,11 @@ public function setBaseUrl(string $baseUrl): void; public function setSecurity(SecurityInterface $security): void; - public function addOperation(string $operationId, string $method, string $path, int $statusCode, TypeInterface|ContentType $schema): OperationBuilderInterface; + public function addOperation(string $operationId, string $method, string $path, int $statusCode, PropertyTypeAbstract|ContentType $schema): OperationBuilderInterface; public function addDefinitions(DefinitionsInterface $definitions): self; - public function addType(string $name, TypeInterface $schema): self; + public function addType(string $name, DefinitionTypeAbstract $schema): self; public function getSpecification(): SpecificationInterface; } diff --git a/src/Generator/Client/LanguageAbstract.php b/src/Generator/Client/LanguageAbstract.php index e924a5f..29594d0 100644 --- a/src/Generator/Client/LanguageAbstract.php +++ b/src/Generator/Client/LanguageAbstract.php @@ -151,8 +151,7 @@ public function generate(SpecificationInterface $specification): Generator\Code\ protected function generateSchema(DefinitionsInterface $definitions, Generator\Code\Chunks $chunks): void { - $schema = new Schema(TypeFactory::getAny(), $definitions); - $result = $this->generator->generate($schema); + $result = $this->generator->generate(new Schema($definitions, null)); if ($result instanceof Generator\Code\Chunks) { foreach ($result->getChunks() as $identifier => $code) { diff --git a/src/Generator/Client/LanguageBuilder.php b/src/Generator/Client/LanguageBuilder.php index 9f6ffec..1fa85db 100644 --- a/src/Generator/Client/LanguageBuilder.php +++ b/src/Generator/Client/LanguageBuilder.php @@ -38,9 +38,13 @@ use PSX\Schema\Generator\TypeAwareInterface; use PSX\Schema\GeneratorInterface; use PSX\Schema\Type\AnyType; +use PSX\Schema\Type\ArrayPropertyType; use PSX\Schema\Type\ArrayType; use PSX\Schema\Type\IntersectionType; +use PSX\Schema\Type\MapPropertyType; use PSX\Schema\Type\MapType; +use PSX\Schema\Type\PropertyTypeAbstract; +use PSX\Schema\Type\ReferencePropertyType; use PSX\Schema\Type\ReferenceType; use PSX\Schema\Type\StructType; use PSX\Schema\Type\UnionType; @@ -164,7 +168,7 @@ private function getOperations(array $operations, DefinitionsInterface $definiti } elseif ($argument->getIn() === ArgumentInterface::IN_QUERY) { $query[$normalized] = new Dto\Argument($argument->getIn(), $this->newType($argument->getSchema(), true, $definitions, Type\GeneratorInterface::CONTEXT_CLIENT | Type\GeneratorInterface::CONTEXT_REQUEST)); $queryNames[$normalized] = $realName; - if ($argument->getSchema() instanceof ReferenceType) { + if ($argument->getSchema() instanceof ReferencePropertyType) { $queryStructNames[] = $realName; } } elseif ($argument->getIn() === ArgumentInterface::IN_BODY) { @@ -259,14 +263,14 @@ private function getOperations(array $operations, DefinitionsInterface $definiti return $result; } - private function getInnerSchema(TypeInterface $type, DefinitionsInterface $definitions): ?Dto\Type + private function getInnerSchema(PropertyTypeAbstract $type, DefinitionsInterface $definitions): ?Dto\Type { - if ($type instanceof MapType) { - $return = $this->newType($type->getAdditionalProperties(), false, $definitions, Type\GeneratorInterface::CONTEXT_CLIENT | Type\GeneratorInterface::CONTEXT_RESPONSE); + if ($type instanceof MapPropertyType) { + $return = $this->newType($type->getSchema(), false, $definitions, Type\GeneratorInterface::CONTEXT_CLIENT | Type\GeneratorInterface::CONTEXT_RESPONSE); $return->isMap = true; return $return; - } elseif ($type instanceof ArrayType) { - $return = $this->newType($type->getItems(), false, $definitions, Type\GeneratorInterface::CONTEXT_CLIENT | Type\GeneratorInterface::CONTEXT_RESPONSE); + } elseif ($type instanceof ArrayPropertyType) { + $return = $this->newType($type->getSchema(), false, $definitions, Type\GeneratorInterface::CONTEXT_CLIENT | Type\GeneratorInterface::CONTEXT_RESPONSE); $return->isArray = true; return $return; } else { @@ -274,25 +278,8 @@ private function getInnerSchema(TypeInterface $type, DefinitionsInterface $defin } } - /** - * @throws InvalidTypeException - * @throws TypeNotFoundException - */ - private function newType(TypeInterface|ContentType $type, bool $optional, DefinitionsInterface $definitions, int $context): Dto\Type + private function newType(PropertyTypeAbstract|ContentType $type, bool $optional, DefinitionsInterface $definitions, int $context): Dto\Type { - if ($type instanceof ReferenceType) { - // in case we have a reference type we take a look at the reference, normally this is a struct type but in - // some special cases we need to extract the type - $refType = $definitions->getType($type->getRef()); - if ($refType instanceof ReferenceType) { - $refType = $definitions->getType($refType->getRef()); - } - - if (!$refType instanceof StructType && !$refType instanceof MapType && !$refType instanceof AnyType) { - throw new InvalidTypeException('A reference can only point to a struct or map type, got: ' . get_class($refType) . ' for reference: ' . $type->getRef()); - } - } - if ($type instanceof ContentType) { $dataType = $this->typeGenerator->getContentType($type, $context); $docType = $dataType; @@ -311,27 +298,19 @@ private function newType(TypeInterface|ContentType $type, bool $optional, Defini /** * @throws GeneratorException */ - private function resolveImport(TypeInterface $type, array &$imports): void + private function resolveImport(PropertyTypeAbstract $type, array &$imports): void { - if ($type instanceof ReferenceType) { - $this->buildImport($type->getRef(), $imports); + if ($type instanceof ReferencePropertyType) { + $this->buildImport($type->getTarget(), $imports); if ($type->getTemplate()) { foreach ($type->getTemplate() as $typeRef) { $this->buildImport($typeRef, $imports); } } - } elseif ($type instanceof MapType && $type->getAdditionalProperties() instanceof TypeInterface) { - $this->resolveImport($type->getAdditionalProperties(), $imports); - } elseif ($type instanceof ArrayType && $type->getItems() instanceof TypeInterface) { - $this->resolveImport($type->getItems(), $imports); - } elseif ($type instanceof UnionType && $type->getOneOf()) { - foreach ($type->getOneOf() as $item) { - $this->resolveImport($item, $imports); - } - } elseif ($type instanceof IntersectionType) { - foreach ($type->getAllOf() as $item) { - $this->resolveImport($item, $imports); - } + } elseif ($type instanceof MapPropertyType && $type->getSchema() instanceof PropertyTypeAbstract) { + $this->resolveImport($type->getSchema(), $imports); + } elseif ($type instanceof ArrayPropertyType && $type->getSchema() instanceof PropertyTypeAbstract) { + $this->resolveImport($type->getSchema(), $imports); } } diff --git a/src/Generator/Client/Util/Naming.php b/src/Generator/Client/Util/Naming.php index 52426b8..ab81566 100644 --- a/src/Generator/Client/Util/Naming.php +++ b/src/Generator/Client/Util/Naming.php @@ -23,8 +23,12 @@ use PSX\Api\Exception\InvalidTypeException; use PSX\Schema\ContentType; use PSX\Schema\Generator\Normalizer\NormalizerInterface; +use PSX\Schema\Type\ArrayPropertyType; use PSX\Schema\Type\ArrayType; +use PSX\Schema\Type\MapPropertyType; use PSX\Schema\Type\MapType; +use PSX\Schema\Type\PropertyTypeAbstract; +use PSX\Schema\Type\ReferencePropertyType; use PSX\Schema\Type\ReferenceType; use PSX\Schema\Type\StringType; use PSX\Schema\TypeInterface; @@ -55,7 +59,10 @@ public function buildMethodNameByTag(string $tagName): string return $this->normalizer->method($tagName); } - public function buildExceptionClassNameByType(TypeInterface|ContentType $type): string + /** + * @throws InvalidTypeException + */ + public function buildExceptionClassNameByType(PropertyTypeAbstract|ContentType $type): string { if ($type instanceof ContentType) { return match ($type->getShape()) { @@ -66,12 +73,12 @@ public function buildExceptionClassNameByType(TypeInterface|ContentType $type): ContentType::TEXT => 'TextException', ContentType::XML => 'XmlException', }; - } elseif ($type instanceof ReferenceType) { - return $this->normalizer->class($type->getRef(), 'Exception'); - } elseif ($type instanceof MapType) { - return 'Map' . $this->buildExceptionClassNameByType($type->getAdditionalProperties()); - } elseif ($type instanceof ArrayType) { - return 'Array' . $this->buildExceptionClassNameByType($type->getItems()); + } elseif ($type instanceof ReferencePropertyType) { + return $this->normalizer->class($type->getTarget(), 'Exception'); + } elseif ($type instanceof MapPropertyType) { + return 'Map' . $this->buildExceptionClassNameByType($type->getSchema()); + } elseif ($type instanceof ArrayPropertyType) { + return 'Array' . $this->buildExceptionClassNameByType($type->getSchema()); } else { throw new InvalidTypeException('Provided an invalid type must be reference, map or array type'); } diff --git a/src/Generator/Markup/MarkupAbstract.php b/src/Generator/Markup/MarkupAbstract.php index a81ac60..f60cc5c 100644 --- a/src/Generator/Markup/MarkupAbstract.php +++ b/src/Generator/Markup/MarkupAbstract.php @@ -93,7 +93,7 @@ protected function startLines(Dto\Client $client): array protected function generateSchema(DefinitionsInterface $definitions): string { - $schema = new Schema(TypeFactory::getAny(), $definitions); + $schema = new Schema($definitions, null); $return = $this->generator->generate($schema); return $return; diff --git a/src/Generator/Server/PHP.php b/src/Generator/Server/PHP.php index edc11a1..b960d31 100644 --- a/src/Generator/Server/PHP.php +++ b/src/Generator/Server/PHP.php @@ -25,6 +25,8 @@ use PSX\Schema\ContentType; use PSX\Schema\Generator; use PSX\Schema\GeneratorInterface as SchemaGeneratorInterface; +use PSX\Schema\Type\PropertyTypeAbstract; +use PSX\Schema\Type\ReferencePropertyType; use PSX\Schema\Type\ReferenceType; use PSX\Schema\TypeInterface; @@ -119,9 +121,9 @@ protected function generateFooter(File $file): string return $controller; } - protected function generateArgumentPath(string $rawName, string $variableName, string $type, TypeInterface|ContentType $argumentType): string + protected function generateArgumentPath(string $rawName, string $variableName, string $type, PropertyTypeAbstract|ContentType $argumentType): string { - if ($argumentType instanceof ReferenceType) { + if ($argumentType instanceof ReferencePropertyType) { $type = 'Model\\' . $type; } @@ -132,9 +134,9 @@ protected function generateArgumentPath(string $rawName, string $variableName, s } } - protected function generateArgumentQuery(string $rawName, string $variableName, string $type, TypeInterface|ContentType $argumentType): string + protected function generateArgumentQuery(string $rawName, string $variableName, string $type, PropertyTypeAbstract|ContentType $argumentType): string { - if ($argumentType instanceof ReferenceType) { + if ($argumentType instanceof ReferencePropertyType) { $type = 'Model\\' . $type; } @@ -145,9 +147,9 @@ protected function generateArgumentQuery(string $rawName, string $variableName, } } - protected function generateArgumentHeader(string $rawName, string $variableName, string $type, TypeInterface|ContentType $argumentType): string + protected function generateArgumentHeader(string $rawName, string $variableName, string $type, PropertyTypeAbstract|ContentType $argumentType): string { - if ($argumentType instanceof ReferenceType) { + if ($argumentType instanceof ReferencePropertyType) { $type = 'Model\\' . $type; } @@ -158,18 +160,18 @@ protected function generateArgumentHeader(string $rawName, string $variableName, } } - protected function generateArgumentBody(string $variableName, string $type, TypeInterface|ContentType $argumentType): string + protected function generateArgumentBody(string $variableName, string $type, PropertyTypeAbstract|ContentType $argumentType): string { - if ($argumentType instanceof ReferenceType) { + if ($argumentType instanceof ReferencePropertyType) { $type = 'Model\\' . $type; } return '#[Body] ' . $type . ' $' . $variableName; } - protected function generateMethod(string $operationName, OperationInterface $operation, array $arguments, string $type, TypeInterface|ContentType $returnType): string + protected function generateMethod(string $operationName, OperationInterface $operation, array $arguments, string $type, PropertyTypeAbstract|ContentType $returnType): string { - if ($returnType instanceof ReferenceType) { + if ($returnType instanceof ReferencePropertyType) { $type = 'Model\\' . $type; } diff --git a/src/Generator/Server/ServerAbstract.php b/src/Generator/Server/ServerAbstract.php index 47b1443..89d7e72 100644 --- a/src/Generator/Server/ServerAbstract.php +++ b/src/Generator/Server/ServerAbstract.php @@ -41,14 +41,15 @@ use PSX\Schema\Generator\TypeAwareInterface; use PSX\Schema\GeneratorInterface as SchemaGeneratorInterface; use PSX\Schema\Schema; -use PSX\Schema\Type\AnyType; +use PSX\Schema\Type\ArrayPropertyType; use PSX\Schema\Type\ArrayType; use PSX\Schema\Type\IntersectionType; +use PSX\Schema\Type\MapPropertyType; use PSX\Schema\Type\MapType; +use PSX\Schema\Type\PropertyTypeAbstract; +use PSX\Schema\Type\ReferencePropertyType; use PSX\Schema\Type\ReferenceType; -use PSX\Schema\Type\StructType; use PSX\Schema\Type\UnionType; -use PSX\Schema\TypeFactory; use PSX\Schema\TypeInterface; use Twig\Environment; use Twig\Loader\FilesystemLoader; @@ -150,15 +151,15 @@ abstract protected function getFileExtension(): string; abstract protected function generateHeader(File $file, array $imports): string; abstract protected function generateFooter(File $file): string; - abstract protected function generateArgumentPath(string $rawName, string $variableName, string $type, TypeInterface|ContentType $argumentType): string; - abstract protected function generateArgumentQuery(string $rawName, string $variableName, string $type, TypeInterface|ContentType $argumentType): string; - abstract protected function generateArgumentHeader(string $rawName, string $variableName, string $type, TypeInterface|ContentType $argumentType): string; - abstract protected function generateArgumentBody(string $variableName, string $type, TypeInterface|ContentType $argumentType): string; + abstract protected function generateArgumentPath(string $rawName, string $variableName, string $type, PropertyTypeAbstract|ContentType $argumentType): string; + abstract protected function generateArgumentQuery(string $rawName, string $variableName, string $type, PropertyTypeAbstract|ContentType $argumentType): string; + abstract protected function generateArgumentHeader(string $rawName, string $variableName, string $type, PropertyTypeAbstract|ContentType $argumentType): string; + abstract protected function generateArgumentBody(string $variableName, string $type, PropertyTypeAbstract|ContentType $argumentType): string; /** * @param array $arguments */ - abstract protected function generateMethod(string $operationName, OperationInterface $operation, array $arguments, string $type, TypeInterface|ContentType $returnType): string; + abstract protected function generateMethod(string $operationName, OperationInterface $operation, array $arguments, string $type, PropertyTypeAbstract|ContentType $returnType): string; protected function buildControllerFileName(string $name): string { @@ -185,21 +186,8 @@ protected function buildFolderStructure(SpecificationInterface $specification): * @throws InvalidTypeException * @throws TypeNotFoundException */ - protected function newType(TypeInterface|ContentType $type, DefinitionsInterface $definitions, int $context): Dto\Type + protected function newType(PropertyTypeAbstract|ContentType $type, DefinitionsInterface $definitions, int $context): Dto\Type { - if ($type instanceof ReferenceType) { - // in case we have a reference type we take a look at the reference, normally this is a struct type but in - // some special cases we need to extract the type - $refType = $definitions->getType($type->getRef()); - if ($refType instanceof ReferenceType) { - $refType = $definitions->getType($refType->getRef()); - } - - if (!$refType instanceof StructType && !$refType instanceof MapType && !$refType instanceof AnyType) { - throw new InvalidTypeException('A reference can only point to a struct or map type, got: ' . get_class($refType) . ' for reference: ' . $type->getRef()); - } - } - if ($type instanceof ContentType) { $dataType = $this->typeGenerator->getContentType($type, $context); $docType = $dataType; @@ -216,8 +204,7 @@ protected function newType(TypeInterface|ContentType $type, DefinitionsInterface protected function generateSchema(DefinitionsInterface $definitions, Generator\Code\Chunks $chunks): void { - $schema = new Schema(TypeFactory::getAny(), $definitions); - $result = $this->generator->generate($schema); + $result = $this->generator->generate(new Schema($definitions, null)); if ($result instanceof Generator\Code\Chunks) { foreach ($result->getChunks() as $identifier => $code) { @@ -251,7 +238,7 @@ private function generateControllerFile(File $file, SpecificationInterface $spec $args[] = $this->generateArgumentBody($variableName, $type->type, $argumentType); } - if ($argumentType instanceof TypeInterface) { + if ($argumentType instanceof PropertyTypeAbstract) { $this->resolveImport($argumentType, $imports); } } @@ -259,7 +246,7 @@ private function generateControllerFile(File $file, SpecificationInterface $spec $returnType = $operation->getReturn()->getSchema(); $type = $this->newType($returnType, $specification->getDefinitions(), Type\GeneratorInterface::CONTEXT_SERVER | Type\GeneratorInterface::CONTEXT_RESPONSE); - if ($returnType instanceof TypeInterface) { + if ($returnType instanceof PropertyTypeAbstract) { $this->resolveImport($returnType, $imports); } @@ -273,27 +260,19 @@ private function generateControllerFile(File $file, SpecificationInterface $spec return $this->getFileContent($result, $file->getName()); } - private function resolveImport(TypeInterface $type, array &$imports): void + private function resolveImport(PropertyTypeAbstract $type, array &$imports): void { - if ($type instanceof ReferenceType) { - $imports[$this->normalizer->file($type->getRef())] = $this->normalizer->class($type->getRef()); + if ($type instanceof ReferencePropertyType) { + $imports[$this->normalizer->file($type->getTarget())] = $this->normalizer->class($type->getTarget()); if ($type->getTemplate()) { foreach ($type->getTemplate() as $typeRef) { $imports[$this->normalizer->file($typeRef)] = $this->normalizer->class($typeRef); } } - } elseif ($type instanceof MapType && $type->getAdditionalProperties() instanceof TypeInterface) { - $this->resolveImport($type->getAdditionalProperties(), $imports); - } elseif ($type instanceof ArrayType && $type->getItems() instanceof TypeInterface) { - $this->resolveImport($type->getItems(), $imports); - } elseif ($type instanceof UnionType && $type->getOneOf()) { - foreach ($type->getOneOf() as $item) { - $this->resolveImport($item, $imports); - } - } elseif ($type instanceof IntersectionType) { - foreach ($type->getAllOf() as $item) { - $this->resolveImport($item, $imports); - } + } elseif ($type instanceof MapPropertyType && $type->getSchema() instanceof PropertyTypeAbstract) { + $this->resolveImport($type->getSchema(), $imports); + } elseif ($type instanceof ArrayPropertyType && $type->getSchema() instanceof PropertyTypeAbstract) { + $this->resolveImport($type->getSchema(), $imports); } } diff --git a/src/Generator/Spec/OpenAPI.php b/src/Generator/Spec/OpenAPI.php index f78180c..802137a 100644 --- a/src/Generator/Spec/OpenAPI.php +++ b/src/Generator/Spec/OpenAPI.php @@ -51,11 +51,16 @@ use PSX\OpenAPI\SecuritySchemes; use PSX\OpenAPI\Server; use PSX\OpenAPI\Tag; +use PSX\Schema\Definitions; use PSX\Schema\DefinitionsInterface; use PSX\Schema\Generator; use PSX\Schema\Parser\Popo\Dumper; use PSX\Schema\Type\ArrayType; +use PSX\Schema\Type\ArrayTypeInterface; use PSX\Schema\Type\MapType; +use PSX\Schema\Type\MapTypeInterface; +use PSX\Schema\Type\PropertyTypeAbstract; +use PSX\Schema\Type\ReferencePropertyType; use PSX\Schema\Type\ReferenceType; use PSX\Schema\TypeFactory; use PSX\Schema\TypeInterface; @@ -128,7 +133,7 @@ protected function buildDeclaration(Paths $paths, DefinitionsInterface $definiti $server = new Server(); $server->setUrl($baseUrl); - $result = $this->generator->toArray(TypeFactory::getAny(), $definitions); + $result = $this->generator->toArray($definitions, null); $schemas = new Schemas(); foreach ($result['definitions'] as $name => $schema) { @@ -231,17 +236,12 @@ protected function buildPathItem(array $operations, DefinitionsInterface $defini return $pathItem; } - protected function newParameter(TypeInterface $type, bool $required, DefinitionsInterface $definitions): Parameter + protected function newParameter(PropertyTypeAbstract $type, bool $required, DefinitionsInterface $definitions): Parameter { - $schema = $this->generator->toArray($type, $definitions); - if (isset($schema['definitions'])) { - unset($schema['definitions']); - } - $param = new Parameter(); $param->setDescription($type->getDescription()); $param->setRequired($required); - $param->setSchema($schema); + $param->setSchema($this->generator->toProperty($type, $definitions)); return $param; } @@ -268,22 +268,22 @@ private function getMediaTypes(TypeInterface $type, DefinitionsInterface $defini private function resolveSchema(TypeInterface $type, DefinitionsInterface $definitions): \stdClass { - if ($type instanceof ReferenceType) { + if ($type instanceof ReferencePropertyType) { return (object) [ - '$ref' => '#/components/schemas/' . $type->getRef(), + '$ref' => '#/components/schemas/' . $type->getTarget(), ]; - } elseif ($type instanceof MapType) { + } elseif ($type instanceof MapTypeInterface) { return (object) [ 'type' => 'object', - 'additionalProperties' => $this->resolveSchema($type->getAdditionalProperties(), $definitions), + 'additionalProperties' => $this->resolveSchema($type->getSchema(), $definitions), ]; - } elseif ($type instanceof ArrayType) { + } elseif ($type instanceof ArrayTypeInterface) { return (object) [ 'type' => 'array', - 'items' => $this->resolveSchema($type->getItems(), $definitions), + 'items' => $this->resolveSchema($type->getSchema(), $definitions), ]; } else { - return (object) $this->generator->toArray($type, $definitions); + return (object) $this->generator->toArray($definitions, null); } } diff --git a/src/Generator/Spec/TypeAPI.php b/src/Generator/Spec/TypeAPI.php index c2ccbce..c86e7b8 100644 --- a/src/Generator/Spec/TypeAPI.php +++ b/src/Generator/Spec/TypeAPI.php @@ -73,7 +73,7 @@ public function generate(SpecificationInterface $specification): Generator\Code\ private function generateDefinitions(DefinitionsInterface $definitions): ?array { $generator = new Generator\TypeSchema(); - $schema = $generator->toArray(TypeFactory::getAny(), $definitions); + $schema = $generator->toArray($definitions, null); return $schema['definitions'] ?? null; } diff --git a/src/Inspector/ChangelogGenerator.php b/src/Inspector/ChangelogGenerator.php index b32a002..8a084ef 100644 --- a/src/Inspector/ChangelogGenerator.php +++ b/src/Inspector/ChangelogGenerator.php @@ -26,8 +26,10 @@ use PSX\Api\OperationsInterface; use PSX\Api\SecurityInterface; use PSX\Api\SpecificationInterface; +use PSX\Schema\ContentType; use PSX\Schema\Inspector\ChangelogGenerator as SchemaChangelogGenerator; use PSX\Schema\Inspector\SemVer; +use PSX\Schema\Type\PropertyTypeAbstract; /** * ChangelogGenerator @@ -179,7 +181,7 @@ private function generateArgument(Operation\Argument $left, Operation\Argument $ yield SemVer::PATCH => $this->getMessageChanged(array_merge($path, ['in']), $left->getIn(), $right->getIn()); } - yield from $this->changelogGenerator->generateType($left->getSchema(), $right->getSchema(), implode('.', $path)); + yield from $this->generateSchema($left->getSchema(), $right->getSchema(), $path); } private function generateResponse(Operation\Response $left, Operation\Response $right, array $path): \Generator @@ -188,7 +190,22 @@ private function generateResponse(Operation\Response $left, Operation\Response $ yield SemVer::PATCH => $this->getMessageChanged(array_merge($path, ['code']), $left->getCode(), $right->getCode()); } - yield from $this->changelogGenerator->generateType($left->getSchema(), $right->getSchema(), implode('.', $path)); + yield from $this->generateSchema($left->getSchema(), $right->getSchema(), $path); + } + + private function generateSchema(ContentType|PropertyTypeAbstract $leftSchema, ContentType|PropertyTypeAbstract $rightSchema, array $path): \Generator + { + if ($leftSchema instanceof ContentType && $rightSchema instanceof ContentType) { + if ($leftSchema->toString() !== $rightSchema->toString()) { + yield SemVer::MAJOR => $this->getMessageChanged(array_merge($path, ['contentType']), $leftSchema->toString(), $rightSchema->toString()); + } + } elseif ($leftSchema instanceof ContentType && $rightSchema instanceof PropertyTypeAbstract) { + yield SemVer::MAJOR => $this->getMessageChanged(array_merge($path, ['contentType']), $leftSchema->toString(), 'schema'); + } elseif ($leftSchema instanceof PropertyTypeAbstract && $rightSchema instanceof ContentType) { + yield SemVer::MAJOR => $this->getMessageChanged(array_merge($path, ['contentType']), 'schema', $rightSchema->toString()); + } else { + yield from $this->changelogGenerator->generatePropertyType($leftSchema, $rightSchema, implode('.', $path)); + } } private function getMessageAdded(array $path, string $type = 'Operation'): string diff --git a/src/Operation/Argument.php b/src/Operation/Argument.php index de711ed..7516c0b 100644 --- a/src/Operation/Argument.php +++ b/src/Operation/Argument.php @@ -21,7 +21,7 @@ namespace PSX\Api\Operation; use PSX\Schema\ContentType; -use PSX\Schema\TypeInterface; +use PSX\Schema\Type\PropertyTypeAbstract; /** * Argument @@ -33,10 +33,10 @@ class Argument implements ArgumentInterface, \JsonSerializable { private string $in; - private TypeInterface|ContentType $schema; + private PropertyTypeAbstract|ContentType $schema; private ?string $name; - public function __construct(string $in, TypeInterface|ContentType $schema, ?string $name = null) + public function __construct(string $in, PropertyTypeAbstract|ContentType $schema, ?string $name = null) { if (!in_array($in, [self::IN_PATH, self::IN_HEADER, self::IN_QUERY, self::IN_BODY])) { throw new \InvalidArgumentException('Provided an invalid "in" value, must be one of: ' . implode(', ', [self::IN_PATH, self::IN_HEADER, self::IN_QUERY, self::IN_BODY])); @@ -52,7 +52,7 @@ public function getIn(): string return $this->in; } - public function getSchema(): TypeInterface|ContentType + public function getSchema(): PropertyTypeAbstract|ContentType { return $this->schema; } @@ -65,7 +65,7 @@ public function getName(): ?string public function jsonSerialize(): array { if ($this->schema instanceof ContentType) { - $contentType = $this->schema->value; + $contentType = $this->schema->toString(); $schema = null; } else { $contentType = null; diff --git a/src/Operation/ArgumentInterface.php b/src/Operation/ArgumentInterface.php index ccd3fd5..79ca0be 100644 --- a/src/Operation/ArgumentInterface.php +++ b/src/Operation/ArgumentInterface.php @@ -21,7 +21,7 @@ namespace PSX\Api\Operation; use PSX\Schema\ContentType; -use PSX\Schema\TypeInterface; +use PSX\Schema\Type\PropertyTypeAbstract; /** * ArgumentInterface @@ -39,7 +39,7 @@ interface ArgumentInterface public function getIn(): string; - public function getSchema(): TypeInterface|ContentType; + public function getSchema(): PropertyTypeAbstract|ContentType; public function getName(): ?string; } diff --git a/src/Operation/Arguments.php b/src/Operation/Arguments.php index e536379..c20668f 100644 --- a/src/Operation/Arguments.php +++ b/src/Operation/Arguments.php @@ -42,10 +42,6 @@ public function __construct(array $arguments = []) public function add(string $name, Argument $argument): void { - if ($argument->getSchema() instanceof StructType) { - throw new InvalidArgumentException('It is not allowed to pass a struct type as argument, please add it to the definitions and pass a reference'); - } - $this->container[$name] = $argument; } diff --git a/src/Parser/Attribute.php b/src/Parser/Attribute.php index 41a677a..94ba6c5 100644 --- a/src/Parser/Attribute.php +++ b/src/Parser/Attribute.php @@ -33,26 +33,19 @@ use PSX\Api\Specification; use PSX\Api\SpecificationInterface; use PSX\Api\Util\Inflection; -use PSX\DateTime\Duration; use PSX\DateTime\LocalDate; use PSX\DateTime\LocalDateTime; use PSX\DateTime\LocalTime; -use PSX\DateTime\Period; use PSX\Schema\ContentType; use PSX\Schema\DefinitionsInterface; use PSX\Schema\Exception\InvalidSchemaException; use PSX\Schema\Format; use PSX\Schema\Parser\Context\FilesystemContext; use PSX\Schema\Parser\ContextInterface; +use PSX\Schema\Parser\Popo\ReflectionReader; use PSX\Schema\SchemaManagerInterface; use PSX\Schema\Type; -use PSX\Schema\Type\NumberType; -use PSX\Schema\Type\ScalarType; -use PSX\Schema\Type\StringType; -use PSX\Schema\Type\TypeAbstract; -use PSX\Schema\TypeFactory; use PSX\Schema\TypeInterface; -use PSX\Uri\Uri; use ReflectionClass; /** @@ -66,6 +59,7 @@ class Attribute implements ParserInterface { private SchemaManagerInterface $schemaManager; private BuilderInterface $builder; + private ReflectionReader $reader; private bool $inspectTypeHints; public function __construct(SchemaManagerInterface $schemaManager, BuilderInterface $builder, bool $inspectTypeHints = true) @@ -73,6 +67,7 @@ public function __construct(SchemaManagerInterface $schemaManager, BuilderInterf $this->schemaManager = $schemaManager; $this->builder = $builder; $this->inspectTypeHints = $inspectTypeHints; + $this->reader = new ReflectionReader(); } /** @@ -262,7 +257,7 @@ public function getResponsesInRange(Meta $meta, int $start, int $end): array /** * @throws InvalidSchemaException */ - private function getBodySchema(Attr\SchemaAbstract $annotation, DefinitionsInterface $definitions, string $basePath): TypeInterface|ContentType + private function getBodySchema(Attr\SchemaAbstract $annotation, DefinitionsInterface $definitions, string $basePath): Type\PropertyTypeAbstract|ContentType { if ($annotation->schema instanceof ContentType) { return $annotation->schema; @@ -272,65 +267,30 @@ private function getBodySchema(Attr\SchemaAbstract $annotation, DefinitionsInter $definitions->merge($schema->getDefinitions()); - return $schema->getType(); + return Type\Factory\PropertyTypeFactory::getReference($schema->getRoot()); } - /** - * @throws InvalidSchemaException - */ private function getParameter(Attr\ParamAbstract $param): TypeInterface { $type = match ($param->type) { - Type::INTEGER => TypeFactory::getInteger(), - Type::NUMBER => TypeFactory::getNumber(), - Type::BOOLEAN => TypeFactory::getBoolean(), - default => TypeFactory::getString(), + Type::INTEGER => Type\Factory\PropertyTypeFactory::getInteger(), + Type::NUMBER => Type\Factory\PropertyTypeFactory::getNumber(), + Type::BOOLEAN => Type\Factory\PropertyTypeFactory::getBoolean(), + default => Type\Factory\PropertyTypeFactory::getString(), }; - if ($type instanceof TypeAbstract) { + if ($type instanceof Type\PropertyTypeAbstract) { $description = $param->description; if ($description !== null) { $type->setDescription($description); } } - if ($type instanceof ScalarType) { - $enum = $param->enum; - if (is_array($enum)) { - $type->setEnum($enum); - } - } - - if ($type instanceof StringType) { - $minLength = $param->minLength; - if ($minLength !== null) { - $type->setMinLength($minLength); - } - - $maxLength = $param->maxLength; - if ($maxLength !== null) { - $type->setMaxLength($maxLength); - } - - $pattern = $param->pattern; - if ($pattern !== null) { - $type->setPattern($pattern); - } - + if ($type instanceof Type\StringPropertyType) { $format = $param->format; if ($format !== null) { $type->setFormat($format); } - } elseif ($type instanceof NumberType) { - $minimum = $param->minimum; - if ($minimum !== null) { - $type->setMinimum($minimum); - } - - $maximum = $param->maximum; - if ($maximum !== null) { - $type->setMaximum($maximum); - } } return $type; @@ -546,44 +506,16 @@ private function getParamArgsFromType(string $name, ?\ReflectionType $type, bool return null; } - $return = match ($type->getName()) { - 'string' => [$name, Type::STRING, '', $required, $enum], - 'int' => [$name, Type::INTEGER, '', $required, $enum], - 'float' => [$name, Type::NUMBER, '', $required, $enum], - 'bool' => [$name, Type::BOOLEAN, '', $required, $enum], - 'mixed' => [$name, Type::ANY, '', $required, $enum], - 'resource' => [$name, Type::STRING, '', $required, $enum, null, null, null, Format::BINARY], - LocalDateTime::class, \DateTimeInterface::class, \DateTimeImmutable::class, \DateTime::class => [$name, Type::STRING, '', $required, $enum, null, null, null, Format::DATETIME], - LocalDate::class => [$name, Type::STRING, '', $required, $enum, null, null, null, Format::DATE], - LocalTime::class => [$name, Type::STRING, '', $required, $enum, null, null, null, Format::TIME], - Period::class, \DateInterval::class => [$name, Type::STRING, '', $required, $enum, null, null, null, Format::PERIOD], - Duration::class => [$name, Type::STRING, '', $required, $enum, null, null, null, Format::DURATION], - Uri::class => [$name, Type::STRING, '', $required, $enum, null, null, null, Format::URI], + return match ($type->getName()) { + 'string' => [$name, Type::STRING, ''], + 'int' => [$name, Type::INTEGER, ''], + 'float' => [$name, Type::NUMBER, ''], + 'bool' => [$name, Type::BOOLEAN, ''], + 'mixed' => [$name, Type::ANY, ''], + LocalDate::class => [$name, Type::STRING, '', Format::DATE], + LocalDateTime::class, \DateTimeInterface::class, \DateTimeImmutable::class, \DateTime::class => [$name, Type::STRING, '', Format::DATETIME], + LocalTime::class => [$name, Type::STRING, '', Format::TIME], default => null, }; - - if ($return === null && function_exists('enum_exists') && enum_exists($type->getName())) { - $return = $this->getTypeFromEnum(new \ReflectionEnum($type->getName()), $name, $required); - } - - return $return; - } - - private function getTypeFromEnum(\ReflectionEnum $enum, string $name, bool $required): ?array - { - if (!$enum->isBacked()) { - // we handle only backed enums since we have only in this case a stable value - return null; - } - - $values = []; - $cases = $enum->getCases(); - foreach ($cases as $case) { - if ($case instanceof \ReflectionEnumBackedCase) { - $values[] = $case->getBackingValue(); - } - } - - return $this->getParamArgsFromType($name, $enum->getBackingType(), $required, $values); } } diff --git a/src/Parser/OpenAPI.php b/src/Parser/OpenAPI.php index f05f297..02d69db 100644 --- a/src/Parser/OpenAPI.php +++ b/src/Parser/OpenAPI.php @@ -61,9 +61,14 @@ use PSX\Schema\SchemaManagerInterface; use PSX\Schema\SchemaTraverser; use PSX\Schema\Type\ArrayType; +use PSX\Schema\Type\ArrayTypeInterface; +use PSX\Schema\Type\Factory\PropertyTypeFactory; use PSX\Schema\Type\IntersectionType; use PSX\Schema\Type\MapType; +use PSX\Schema\Type\MapTypeInterface; +use PSX\Schema\Type\ReferencePropertyType; use PSX\Schema\Type\ReferenceType; +use PSX\Schema\Type\StructDefinitionType; use PSX\Schema\Type\StructType; use PSX\Schema\Type\UnionType; use PSX\Schema\TypeFactory; @@ -299,7 +304,7 @@ private function parseParameter(string $in, Parameter|Reference $data): array } $name = $data->getName(); - $type = TypeFactory::getString(); + $type = PropertyTypeFactory::getString(); $required = null; if (!empty($name) && $data->getIn() == $in) { @@ -307,9 +312,9 @@ private function parseParameter(string $in, Parameter|Reference $data): array $schema = $data->getSchema(); if ($schema instanceof \stdClass) { - $type = $this->schemaParser->parseType($schema); - if ($type instanceof ReferenceType) { - $type = $this->definitions->getType($type->getRef()); + $type = $this->schemaParser->parsePropertyType($schema); + if ($type instanceof ReferencePropertyType) { + $type = $this->definitions->getType($type->getTarget()); } } } @@ -384,7 +389,7 @@ private function getSchemaFromMediaTypes(MediaTypes $mediaTypes): ?TypeInterface return null; } - $type = $this->schemaParser->parseType($schema); + $type = $this->schemaParser->parsePropertyType($schema); return $this->transformInlineStruct($type); } @@ -397,37 +402,25 @@ private function getSchemaFromMediaTypes(MediaTypes $mediaTypes): ?TypeInterface */ private function transformInlineStruct(TypeInterface $type): TypeInterface { - if ($type instanceof StructType) { + if ($type instanceof StructDefinitionType) { // we have an inline struct type we automatically add this ot the definitions, since we have no name we generate // it based on the type, this should motivate users to move the definition to the components section $typeName = 'Inline' . substr($this->hashInspector->generateByType($type), 0, 8); $this->definitions->addType($typeName, $type); return TypeFactory::getReference($typeName); - } elseif ($type instanceof MapType) { - $child = $type->getAdditionalProperties(); - if ($child instanceof TypeInterface) { - $r = $this->transformInlineStruct($child); + } elseif ($type instanceof MapTypeInterface) { + $schema = $type->getSchema(); + if ($schema instanceof TypeInterface) { + $r = $this->transformInlineStruct($schema); return TypeFactory::getMap($r); } - } elseif ($type instanceof ArrayType) { - $child = $type->getItems(); - if ($child instanceof TypeInterface) { - $r = $this->transformInlineStruct($child); + } elseif ($type instanceof ArrayTypeInterface) { + $schema = $type->getSchema(); + if ($schema instanceof TypeInterface) { + $r = $this->transformInlineStruct($schema); return TypeFactory::getArray($r); } - } elseif ($type instanceof UnionType) { - $result = []; - foreach ($type->getOneOf() as $child) { - $result[] = $this->transformInlineStruct($child); - } - return TypeFactory::getUnion($result); - } elseif ($type instanceof IntersectionType) { - $result = []; - foreach ($type->getAllOf() as $child) { - $result[] = $this->transformInlineStruct($child); - } - return TypeFactory::getIntersection($result); } return $type; diff --git a/src/Parser/TypeAPI.php b/src/Parser/TypeAPI.php index 22985e0..0232cb9 100644 --- a/src/Parser/TypeAPI.php +++ b/src/Parser/TypeAPI.php @@ -224,7 +224,7 @@ private function parseArgument(\stdClass $data): Operation\Argument throw new ParserException('Property "schema" must be an object'); } - $type = $this->schemaParser->parseType($schema); + $type = $this->schemaParser->parsePropertyType($schema); } $name = $data->name ?? null; @@ -271,7 +271,7 @@ private function parseResponse(\stdClass $data): Operation\Response throw new ParserException('Property "schema" must be an object'); } - $type = $this->schemaParser->parseType($schema); + $type = $this->schemaParser->parsePropertyType($schema); } return new Operation\Response($code, $type); diff --git a/tests/ApiManagerTest.php b/tests/ApiManagerTest.php index b738109..ed64c1b 100644 --- a/tests/ApiManagerTest.php +++ b/tests/ApiManagerTest.php @@ -24,6 +24,7 @@ use PSX\Api\SpecificationInterface; use PSX\Api\Tests\Parser\Attribute\TestController; use PSX\Schema\SchemaManager; +use PSX\Schema\Type\Factory\PropertyTypeFactory; /** * ApiManagerTest @@ -70,8 +71,8 @@ public function testGetBuilder() $schema = $manager->getSchema(__DIR__ . '/Parser/schema/schema.json'); $builder->addDefinitions($schema->getDefinitions()); - $operation = $builder->addOperation('my.operation', 'GET', '/foo', 200, $schema->getType()); - $operation->addArgument('payload', 'body', $schema->getType()); + $operation = $builder->addOperation('my.operation', 'GET', '/foo', 200, PropertyTypeFactory::getReference($schema->getRoot())); + $operation->addArgument('payload', 'body', PropertyTypeFactory::getReference($schema->getRoot())); $operation->setDescription('My operation description'); $operation->setSecurity(['foo']); $operation->setTags(['my_tag']); diff --git a/tests/Console/GenerateCommandTest.php b/tests/Console/GenerateCommandTest.php index bceb8dd..277b8e5 100644 --- a/tests/Console/GenerateCommandTest.php +++ b/tests/Console/GenerateCommandTest.php @@ -46,11 +46,11 @@ public function testGenerateClientPhp() $command = $this->getGenerateCommand(); $commandTester = new CommandTester($command); - $commandTester->execute(array( + $commandTester->execute([ 'type' => LocalRepository::CLIENT_PHP, 'dir' => __DIR__ . '/output', '--config' => 'Acme\\Sdk\\Generated', - )); + ]); $this->assertFileExists(__DIR__ . '/output/sdk-client-php.zip'); } @@ -60,10 +60,10 @@ public function testGenerateSpecOpenAPI() $command = $this->getGenerateCommand(); $commandTester = new CommandTester($command); - $commandTester->execute(array( + $commandTester->execute([ 'type' => LocalRepository::SPEC_OPENAPI, 'dir' => __DIR__ . '/output', - )); + ]); $this->assertFileExists(__DIR__ . '/output/output-spec-openapi.json'); } diff --git a/tests/Console/resource/spec_openapi.json b/tests/Console/resource/spec_openapi.json index 5582763..ee56c31 100644 --- a/tests/Console/resource/spec_openapi.json +++ b/tests/Console/resource/spec_openapi.json @@ -41,10 +41,6 @@ "in": "query", "required": false, "schema": { - "enum": [ - "foo", - "bar" - ], "type": "string" } }, @@ -53,8 +49,7 @@ "in": "query", "required": false, "schema": { - "type": "string", - "pattern": "[A-z]+" + "type": "string" } }, { @@ -78,8 +73,8 @@ "in": "query", "required": false, "schema": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } }, { @@ -157,7 +152,6 @@ } }, "Rating": { - "title": "Rating", "type": "object", "properties": { "author": { @@ -190,11 +184,7 @@ "$ref": "#/components/schemas/Rating" } } - }, - "required": [ - "title", - "artist" - ] + } } } } diff --git a/tests/Generator/Client/PHPTest.php b/tests/Generator/Client/PHPTest.php index 8319a6a..4d33244 100644 --- a/tests/Generator/Client/PHPTest.php +++ b/tests/Generator/Client/PHPTest.php @@ -59,14 +59,6 @@ public function testGenerateCollection() $this->assertFileExists($target . '/Client.php'); } - public function testGenerateComplex() - { - $this->expectException(InvalidTypeException::class); - - $generator = new PHP('http://api.foo.com', Config::of('Foo\\Bar')); - $generator->generate($this->getSpecificationComplex()); - } - public function testGenerateTest() { $generator = new PHP('http://127.0.0.1:8081', Config::of('Sdkgen\\Client\\Tests\\Generated')); diff --git a/tests/Generator/Client/TypeScriptTest.php b/tests/Generator/Client/TypeScriptTest.php index d2c2c5b..41f34f4 100644 --- a/tests/Generator/Client/TypeScriptTest.php +++ b/tests/Generator/Client/TypeScriptTest.php @@ -59,14 +59,6 @@ public function testGenerateCollection() $this->assertFileExists($target . '/Client.ts'); } - public function testGenerateComplex() - { - $this->expectException(InvalidTypeException::class); - - $generator = new TypeScript('http://api.foo.com'); - $generator->generate($this->getSpecificationComplex()); - } - public function testGenerateTest() { $generator = new TypeScript('http://127.0.0.1:8081'); diff --git a/tests/Generator/Client/resource/php/Entry.php b/tests/Generator/Client/resource/php/Entry.php index 96af289..fb2ddff 100644 --- a/tests/Generator/Client/resource/php/Entry.php +++ b/tests/Generator/Client/resource/php/Entry.php @@ -4,17 +4,10 @@ * @see https://sdkgen.app */ -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; - class Entry implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Client/resource/php/EntryCreate.php b/tests/Generator/Client/resource/php/EntryCreate.php index c42b855..43abb95 100644 --- a/tests/Generator/Client/resource/php/EntryCreate.php +++ b/tests/Generator/Client/resource/php/EntryCreate.php @@ -4,19 +4,10 @@ * @see https://sdkgen.app */ -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; -use PSX\Schema\Attribute\Required; - -#[Required(array('title', 'date'))] class EntryCreate implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Client/resource/php/EntryDelete.php b/tests/Generator/Client/resource/php/EntryDelete.php index 14cdf7c..4d8487c 100644 --- a/tests/Generator/Client/resource/php/EntryDelete.php +++ b/tests/Generator/Client/resource/php/EntryDelete.php @@ -4,19 +4,10 @@ * @see https://sdkgen.app */ -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; -use PSX\Schema\Attribute\Required; - -#[Required(array('id'))] class EntryDelete implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Client/resource/php/EntryPatch.php b/tests/Generator/Client/resource/php/EntryPatch.php index b606048..340209c 100644 --- a/tests/Generator/Client/resource/php/EntryPatch.php +++ b/tests/Generator/Client/resource/php/EntryPatch.php @@ -4,19 +4,10 @@ * @see https://sdkgen.app */ -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; -use PSX\Schema\Attribute\Required; - -#[Required(array('id'))] class EntryPatch implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Client/resource/php/EntryUpdate.php b/tests/Generator/Client/resource/php/EntryUpdate.php index 1a7f995..829472b 100644 --- a/tests/Generator/Client/resource/php/EntryUpdate.php +++ b/tests/Generator/Client/resource/php/EntryUpdate.php @@ -4,19 +4,10 @@ * @see https://sdkgen.app */ -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; -use PSX\Schema\Attribute\Required; - -#[Required(array('id'))] class EntryUpdate implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Client/resource/php_collection/Entry.php b/tests/Generator/Client/resource/php_collection/Entry.php index 2e117a4..3cb3e43 100644 --- a/tests/Generator/Client/resource/php_collection/Entry.php +++ b/tests/Generator/Client/resource/php_collection/Entry.php @@ -6,17 +6,11 @@ namespace Foo\Bar; -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; class Entry implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Client/resource/php_collection/EntryCreate.php b/tests/Generator/Client/resource/php_collection/EntryCreate.php index 94b1813..a55a14f 100644 --- a/tests/Generator/Client/resource/php_collection/EntryCreate.php +++ b/tests/Generator/Client/resource/php_collection/EntryCreate.php @@ -6,19 +6,11 @@ namespace Foo\Bar; -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; -use PSX\Schema\Attribute\Required; -#[Required(array('title', 'date'))] class EntryCreate implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Client/resource/php_test/TestMapObject.php b/tests/Generator/Client/resource/php_test/TestMapObject.php index cab6d28..6cb8841 100644 --- a/tests/Generator/Client/resource/php_test/TestMapObject.php +++ b/tests/Generator/Client/resource/php_test/TestMapObject.php @@ -7,8 +7,8 @@ namespace Sdkgen\Client\Tests\Generated; /** - * @extends \PSX\Record\Record + * @extends \ArrayObject */ -class TestMapObject extends \PSX\Record\Record +class TestMapObject extends \ArrayObject { } diff --git a/tests/Generator/Client/resource/php_test/TestMapScalar.php b/tests/Generator/Client/resource/php_test/TestMapScalar.php index 01437af..862bce6 100644 --- a/tests/Generator/Client/resource/php_test/TestMapScalar.php +++ b/tests/Generator/Client/resource/php_test/TestMapScalar.php @@ -7,8 +7,8 @@ namespace Sdkgen\Client\Tests\Generated; /** - * @extends \PSX\Record\Record + * @extends \ArrayObject */ -class TestMapScalar extends \PSX\Record\Record +class TestMapScalar extends \ArrayObject { } diff --git a/tests/Generator/Client/resource/typescript/Client.ts b/tests/Generator/Client/resource/typescript/Client.ts index bd22b11..f79c75e 100644 --- a/tests/Generator/Client/resource/typescript/Client.ts +++ b/tests/Generator/Client/resource/typescript/Client.ts @@ -114,12 +114,12 @@ export class Client extends ClientAbstract { } /** - * @returns {Promise>} + * @returns {Promise>} * @throws {EntryMessageException} * @throws {MapEntryMessageException} * @throws {ClientException} */ - public async update(name: string, type: string, payload: Record): Promise> { + public async update(name: string, type: string, payload: Map): Promise> { const url = this.parser.url('/foo/:name/:type', { 'name': name, 'type': type, @@ -138,7 +138,7 @@ export class Client extends ClientAbstract { }; try { - const response = await this.httpClient.request>(params); + const response = await this.httpClient.request>(params); return response.data; } catch (error) { if (error instanceof ClientException) { diff --git a/tests/Generator/Client/resource/typescript/Entry.ts b/tests/Generator/Client/resource/typescript/Entry.ts index b50aaa0..9cd75df 100644 --- a/tests/Generator/Client/resource/typescript/Entry.ts +++ b/tests/Generator/Client/resource/typescript/Entry.ts @@ -3,7 +3,7 @@ * {@link https://sdkgen.app} */ -export interface Entry { +export class Entry { id?: number userId?: number title?: string diff --git a/tests/Generator/Client/resource/typescript/EntryCollection.ts b/tests/Generator/Client/resource/typescript/EntryCollection.ts index 1f8e50b..b7893c5 100644 --- a/tests/Generator/Client/resource/typescript/EntryCollection.ts +++ b/tests/Generator/Client/resource/typescript/EntryCollection.ts @@ -4,6 +4,6 @@ */ import {Entry} from "./Entry"; -export interface EntryCollection { +export class EntryCollection { entry?: Array } diff --git a/tests/Generator/Client/resource/typescript/EntryCreate.ts b/tests/Generator/Client/resource/typescript/EntryCreate.ts index ec66486..ba35a58 100644 --- a/tests/Generator/Client/resource/typescript/EntryCreate.ts +++ b/tests/Generator/Client/resource/typescript/EntryCreate.ts @@ -3,9 +3,9 @@ * {@link https://sdkgen.app} */ -export interface EntryCreate { +export class EntryCreate { id?: number userId?: number - title: string - date: string + title?: string + date?: string } diff --git a/tests/Generator/Client/resource/typescript/EntryDelete.ts b/tests/Generator/Client/resource/typescript/EntryDelete.ts index 102bbf9..2b48203 100644 --- a/tests/Generator/Client/resource/typescript/EntryDelete.ts +++ b/tests/Generator/Client/resource/typescript/EntryDelete.ts @@ -3,8 +3,8 @@ * {@link https://sdkgen.app} */ -export interface EntryDelete { - id: number +export class EntryDelete { + id?: number userId?: number title?: string date?: string diff --git a/tests/Generator/Client/resource/typescript/EntryMessage.ts b/tests/Generator/Client/resource/typescript/EntryMessage.ts index 3c733c2..eecb5a7 100644 --- a/tests/Generator/Client/resource/typescript/EntryMessage.ts +++ b/tests/Generator/Client/resource/typescript/EntryMessage.ts @@ -3,7 +3,7 @@ * {@link https://sdkgen.app} */ -export interface EntryMessage { +export class EntryMessage { success?: boolean message?: string } diff --git a/tests/Generator/Client/resource/typescript/EntryPatch.ts b/tests/Generator/Client/resource/typescript/EntryPatch.ts index d901ed0..8be6551 100644 --- a/tests/Generator/Client/resource/typescript/EntryPatch.ts +++ b/tests/Generator/Client/resource/typescript/EntryPatch.ts @@ -3,8 +3,8 @@ * {@link https://sdkgen.app} */ -export interface EntryPatch { - id: number +export class EntryPatch { + id?: number userId?: number title?: string date?: string diff --git a/tests/Generator/Client/resource/typescript/EntryUpdate.ts b/tests/Generator/Client/resource/typescript/EntryUpdate.ts index 984816c..92b8893 100644 --- a/tests/Generator/Client/resource/typescript/EntryUpdate.ts +++ b/tests/Generator/Client/resource/typescript/EntryUpdate.ts @@ -3,8 +3,8 @@ * {@link https://sdkgen.app} */ -export interface EntryUpdate { - id: number +export class EntryUpdate { + id?: number userId?: number title?: string date?: string diff --git a/tests/Generator/Client/resource/typescript/MapEntryMessageException.ts b/tests/Generator/Client/resource/typescript/MapEntryMessageException.ts index 93b7f79..1480b8b 100644 --- a/tests/Generator/Client/resource/typescript/MapEntryMessageException.ts +++ b/tests/Generator/Client/resource/typescript/MapEntryMessageException.ts @@ -9,11 +9,11 @@ import {EntryMessage} from "./EntryMessage"; export class MapEntryMessageException extends KnownStatusCodeException { - public constructor(private payload: Record) { + public constructor(private payload: Map) { super('The server returned an error'); } - public getPayload(): Record { + public getPayload(): Map { return this.payload; } diff --git a/tests/Generator/Client/resource/typescript_collection/Entry.ts b/tests/Generator/Client/resource/typescript_collection/Entry.ts index b50aaa0..9cd75df 100644 --- a/tests/Generator/Client/resource/typescript_collection/Entry.ts +++ b/tests/Generator/Client/resource/typescript_collection/Entry.ts @@ -3,7 +3,7 @@ * {@link https://sdkgen.app} */ -export interface Entry { +export class Entry { id?: number userId?: number title?: string diff --git a/tests/Generator/Client/resource/typescript_collection/EntryCollection.ts b/tests/Generator/Client/resource/typescript_collection/EntryCollection.ts index 1f8e50b..b7893c5 100644 --- a/tests/Generator/Client/resource/typescript_collection/EntryCollection.ts +++ b/tests/Generator/Client/resource/typescript_collection/EntryCollection.ts @@ -4,6 +4,6 @@ */ import {Entry} from "./Entry"; -export interface EntryCollection { +export class EntryCollection { entry?: Array } diff --git a/tests/Generator/Client/resource/typescript_collection/EntryCreate.ts b/tests/Generator/Client/resource/typescript_collection/EntryCreate.ts index ec66486..ba35a58 100644 --- a/tests/Generator/Client/resource/typescript_collection/EntryCreate.ts +++ b/tests/Generator/Client/resource/typescript_collection/EntryCreate.ts @@ -3,9 +3,9 @@ * {@link https://sdkgen.app} */ -export interface EntryCreate { +export class EntryCreate { id?: number userId?: number - title: string - date: string + title?: string + date?: string } diff --git a/tests/Generator/Client/resource/typescript_collection/EntryMessage.ts b/tests/Generator/Client/resource/typescript_collection/EntryMessage.ts index 3c733c2..eecb5a7 100644 --- a/tests/Generator/Client/resource/typescript_collection/EntryMessage.ts +++ b/tests/Generator/Client/resource/typescript_collection/EntryMessage.ts @@ -3,7 +3,7 @@ * {@link https://sdkgen.app} */ -export interface EntryMessage { +export class EntryMessage { success?: boolean message?: string } diff --git a/tests/Generator/Client/resource/typescript_import/MySchema.ts b/tests/Generator/Client/resource/typescript_import/MySchema.ts index f50ce9c..6eb1744 100644 --- a/tests/Generator/Client/resource/typescript_import/MySchema.ts +++ b/tests/Generator/Client/resource/typescript_import/MySchema.ts @@ -4,6 +4,6 @@ */ import {MyType} from "./../foo/MyType"; -export interface MySchema { +export class MySchema { foo?: MyType } diff --git a/tests/Generator/Client/resource/typescript_test/TestMapObject.ts b/tests/Generator/Client/resource/typescript_test/TestMapObject.ts index bd410ba..65f1c75 100644 --- a/tests/Generator/Client/resource/typescript_test/TestMapObject.ts +++ b/tests/Generator/Client/resource/typescript_test/TestMapObject.ts @@ -4,4 +4,5 @@ */ import {TestObject} from "./TestObject"; -export type TestMapObject = Record; +export class TestMapObject extends Map { +} diff --git a/tests/Generator/Client/resource/typescript_test/TestMapScalar.ts b/tests/Generator/Client/resource/typescript_test/TestMapScalar.ts index 6b48faa..0a44959 100644 --- a/tests/Generator/Client/resource/typescript_test/TestMapScalar.ts +++ b/tests/Generator/Client/resource/typescript_test/TestMapScalar.ts @@ -3,4 +3,5 @@ * {@link https://sdkgen.app} */ -export type TestMapScalar = Record; +export class TestMapScalar extends Map { +} diff --git a/tests/Generator/Client/resource/typescript_test/TestObject.ts b/tests/Generator/Client/resource/typescript_test/TestObject.ts index 659d10f..b0d9011 100644 --- a/tests/Generator/Client/resource/typescript_test/TestObject.ts +++ b/tests/Generator/Client/resource/typescript_test/TestObject.ts @@ -3,7 +3,7 @@ * {@link https://sdkgen.app} */ -export interface TestObject { +export class TestObject { id?: number name?: string } diff --git a/tests/Generator/Client/resource/typescript_test/TestRequest.ts b/tests/Generator/Client/resource/typescript_test/TestRequest.ts index 7c38e0c..daea58e 100644 --- a/tests/Generator/Client/resource/typescript_test/TestRequest.ts +++ b/tests/Generator/Client/resource/typescript_test/TestRequest.ts @@ -6,7 +6,7 @@ import {TestObject} from "./TestObject"; import {TestMapScalar} from "./TestMapScalar"; import {TestMapObject} from "./TestMapObject"; -export interface TestRequest { +export class TestRequest { int?: number float?: number string?: string diff --git a/tests/Generator/Client/resource/typescript_test/TestResponse.ts b/tests/Generator/Client/resource/typescript_test/TestResponse.ts index f560e24..0a77195 100644 --- a/tests/Generator/Client/resource/typescript_test/TestResponse.ts +++ b/tests/Generator/Client/resource/typescript_test/TestResponse.ts @@ -5,7 +5,7 @@ import {TestMapScalar} from "./TestMapScalar"; import {TestRequest} from "./TestRequest"; -export interface TestResponse { +export class TestResponse { args?: TestMapScalar data?: string files?: TestMapScalar diff --git a/tests/Generator/GeneratorTestCase.php b/tests/Generator/GeneratorTestCase.php index c32840c..61e2d99 100644 --- a/tests/Generator/GeneratorTestCase.php +++ b/tests/Generator/GeneratorTestCase.php @@ -30,6 +30,9 @@ use PSX\Schema\Definitions; use PSX\Schema\Format; use PSX\Schema\Generator\Code\Chunks; +use PSX\Schema\Type\Factory\DefinitionTypeFactory; +use PSX\Schema\Type\Factory\PropertyTypeFactory; +use PSX\Schema\Type\ReferencePropertyType; use PSX\Schema\Type\StructType; use PSX\Schema\TypeFactory; use PSX\Schema\TypeInterface; @@ -55,52 +58,46 @@ protected function getSpecification(): SpecificationInterface $delete = $this->addSchema($builder, Schema\Delete::class); $patch = $this->addSchema($builder, Schema\Patch::class); - $operation = $builder->addOperation('get', 'GET', '/foo/:name/:type', 200, $collection); + $operation = $builder->addOperation('get', 'GET', '/foo/:name/:type', 200, PropertyTypeFactory::getReference($collection)); $operation->setDescription('Returns a collection'); - $operation->addArgument('name', ArgumentInterface::IN_PATH, TypeFactory::getString() - ->setDescription('Name parameter') - ->setMinLength(0) - ->setMaxLength(16) - ->setPattern('[A-z]+')); - $operation->addArgument('type', ArgumentInterface::IN_PATH, TypeFactory::getString() - ->setEnum(['foo', 'bar'])); - $operation->addArgument('startIndex', ArgumentInterface::IN_QUERY, TypeFactory::getInteger() - ->setDescription('startIndex parameter') - ->setMinimum(0) - ->setMaximum(32)); - $operation->addArgument('float', ArgumentInterface::IN_QUERY, TypeFactory::getNumber()); - $operation->addArgument('boolean', ArgumentInterface::IN_QUERY, TypeFactory::getBoolean()); - $operation->addArgument('date', ArgumentInterface::IN_QUERY, TypeFactory::getString() + $operation->addArgument('name', ArgumentInterface::IN_PATH, PropertyTypeFactory::getString() + ->setDescription('Name parameter')); + $operation->addArgument('type', ArgumentInterface::IN_PATH, PropertyTypeFactory::getString()); + $operation->addArgument('startIndex', ArgumentInterface::IN_QUERY, PropertyTypeFactory::getInteger() + ->setDescription('startIndex parameter')); + $operation->addArgument('float', ArgumentInterface::IN_QUERY, PropertyTypeFactory::getNumber()); + $operation->addArgument('boolean', ArgumentInterface::IN_QUERY, PropertyTypeFactory::getBoolean()); + $operation->addArgument('date', ArgumentInterface::IN_QUERY, PropertyTypeFactory::getString() ->setFormat(Format::DATE)); - $operation->addArgument('datetime', ArgumentInterface::IN_QUERY, TypeFactory::getString() + $operation->addArgument('datetime', ArgumentInterface::IN_QUERY, PropertyTypeFactory::getString() ->setFormat(Format::DATETIME)); - $operation->addArgument('args', ArgumentInterface::IN_QUERY, TypeFactory::getReference('Entry')); - - $operation = $builder->addOperation('create', 'POST', '/foo/:name/:type', 201, $message); - $operation->addArgument('name', ArgumentInterface::IN_PATH, TypeFactory::getString()); - $operation->addArgument('type', ArgumentInterface::IN_PATH, TypeFactory::getString()); - $operation->addArgument('payload', ArgumentInterface::IN_BODY, $create); - $operation->addThrow(400, $message); - $operation->addThrow(500, $message); - - $operation = $builder->addOperation('update', 'PUT', '/foo/:name/:type', 200, TypeFactory::getMap($message)); - $operation->addArgument('name', ArgumentInterface::IN_PATH, TypeFactory::getString()); - $operation->addArgument('type', ArgumentInterface::IN_PATH, TypeFactory::getString()); - $operation->addArgument('payload', ArgumentInterface::IN_BODY, TypeFactory::getMap($update)); - $operation->addThrow(400, $message); - $operation->addThrow(500, TypeFactory::getMap($message)); - - $operation = $builder->addOperation('delete', 'DELETE', '/foo/:name/:type', 204, $message); - $operation->addArgument('name', ArgumentInterface::IN_PATH, TypeFactory::getString()); - $operation->addArgument('type', ArgumentInterface::IN_PATH, TypeFactory::getString()); - $operation->addArgument('payload', ArgumentInterface::IN_BODY, $delete); - - $operation = $builder->addOperation('patch', 'PATCH', '/foo/:name/:type', 200, TypeFactory::getArray($message)); - $operation->addArgument('name', ArgumentInterface::IN_PATH, TypeFactory::getString()); - $operation->addArgument('type', ArgumentInterface::IN_PATH, TypeFactory::getString()); - $operation->addArgument('payload', ArgumentInterface::IN_BODY, TypeFactory::getArray($patch)); - $operation->addThrow(400, $message); - $operation->addThrow(500, TypeFactory::getArray($message)); + $operation->addArgument('args', ArgumentInterface::IN_QUERY, PropertyTypeFactory::getReference('Entry')); + + $operation = $builder->addOperation('create', 'POST', '/foo/:name/:type', 201, PropertyTypeFactory::getReference($message)); + $operation->addArgument('name', ArgumentInterface::IN_PATH, PropertyTypeFactory::getString()); + $operation->addArgument('type', ArgumentInterface::IN_PATH, PropertyTypeFactory::getString()); + $operation->addArgument('payload', ArgumentInterface::IN_BODY, PropertyTypeFactory::getReference($create)); + $operation->addThrow(400, PropertyTypeFactory::getReference($message)); + $operation->addThrow(500, PropertyTypeFactory::getReference($message)); + + $operation = $builder->addOperation('update', 'PUT', '/foo/:name/:type', 200, PropertyTypeFactory::getMap(PropertyTypeFactory::getReference($message))); + $operation->addArgument('name', ArgumentInterface::IN_PATH, PropertyTypeFactory::getString()); + $operation->addArgument('type', ArgumentInterface::IN_PATH, PropertyTypeFactory::getString()); + $operation->addArgument('payload', ArgumentInterface::IN_BODY, PropertyTypeFactory::getMap(PropertyTypeFactory::getReference($update))); + $operation->addThrow(400, PropertyTypeFactory::getReference($message)); + $operation->addThrow(500, PropertyTypeFactory::getMap(PropertyTypeFactory::getReference($message))); + + $operation = $builder->addOperation('delete', 'DELETE', '/foo/:name/:type', 204, PropertyTypeFactory::getReference($message)); + $operation->addArgument('name', ArgumentInterface::IN_PATH, PropertyTypeFactory::getString()); + $operation->addArgument('type', ArgumentInterface::IN_PATH, PropertyTypeFactory::getString()); + $operation->addArgument('payload', ArgumentInterface::IN_BODY, PropertyTypeFactory::getReference($delete)); + + $operation = $builder->addOperation('patch', 'PATCH', '/foo/:name/:type', 200, PropertyTypeFactory::getArray(PropertyTypeFactory::getReference($message))); + $operation->addArgument('name', ArgumentInterface::IN_PATH, PropertyTypeFactory::getString()); + $operation->addArgument('type', ArgumentInterface::IN_PATH, PropertyTypeFactory::getString()); + $operation->addArgument('payload', ArgumentInterface::IN_BODY, PropertyTypeFactory::getArray(PropertyTypeFactory::getReference($patch))); + $operation->addThrow(400, PropertyTypeFactory::getReference($message)); + $operation->addThrow(500, PropertyTypeFactory::getArray(PropertyTypeFactory::getReference($message))); return $builder->getSpecification(); } @@ -114,51 +111,33 @@ protected function getSpecificationCollection(): SpecificationInterface $message = $this->addSchema($builder, Schema\Message::class); $create = $this->addSchema($builder, Schema\Create::class); - $operation = $builder->addOperation('foo.bar.get', 'GET', '/foo', 200, $collection); + $operation = $builder->addOperation('foo.bar.get', 'GET', '/foo', 200, PropertyTypeFactory::getReference($collection)); $operation->setDescription('Returns a collection'); $operation->setTags(['foo']); - $operation = $builder->addOperation('foo.bar.create', 'POST', '/foo', 201, $message); + $operation = $builder->addOperation('foo.bar.create', 'POST', '/foo', 201, PropertyTypeFactory::getReference($message)); $operation->setTags(['foo']); - $operation->addArgument('payload', 'body', $create); - $operation->addThrow(400, $message); - $operation->addThrow(500, $message); + $operation->addArgument('payload', 'body', PropertyTypeFactory::getReference($create)); + $operation->addThrow(400, PropertyTypeFactory::getReference($message)); + $operation->addThrow(500, PropertyTypeFactory::getReference($message)); - $operation = $builder->addOperation('bar.find', 'GET', '/bar/:foo', 200, $collection); + $operation = $builder->addOperation('bar.find', 'GET', '/bar/:foo', 200, PropertyTypeFactory::getReference($collection)); $operation->setDescription('Returns a collection'); $operation->setTags(['bar']); - $operation->addArgument('foo', 'path', TypeFactory::getString()); + $operation->addArgument('foo', 'path', PropertyTypeFactory::getString()); - $operation = $builder->addOperation('bar.put', 'POST', '/bar/:foo', 201, $message); + $operation = $builder->addOperation('bar.put', 'POST', '/bar/:foo', 201, PropertyTypeFactory::getReference($message)); $operation->setTags(['bar']); - $operation->addArgument('payload', 'body', $create); + $operation->addArgument('payload', 'body', PropertyTypeFactory::getReference($create)); - $operation = $builder->addOperation('foo.baz.get', 'GET', '/bar/$year<[0-9]+>', 200, $collection); + $operation = $builder->addOperation('foo.baz.get', 'GET', '/bar/$year<[0-9]+>', 200, PropertyTypeFactory::getReference($collection)); $operation->setDescription('Returns a collection'); $operation->setTags(['baz']); - $operation->addArgument('year', 'path', TypeFactory::getString()); + $operation->addArgument('year', 'path', PropertyTypeFactory::getString()); - $operation = $builder->addOperation('foo.baz.create', 'POST', '/bar/$year<[0-9]+>', 201, $message); + $operation = $builder->addOperation('foo.baz.create', 'POST', '/bar/$year<[0-9]+>', 201, PropertyTypeFactory::getReference($message)); $operation->setTags(['baz']); - $operation->addArgument('payload', 'body', $create); - - return $builder->getSpecification(); - } - - protected function getSpecificationComplex(): SpecificationInterface - { - $builder = $this->apiManager->getBuilder(); - $builder->setSecurity(new HttpBearer()); - - $complex = $this->addSchema($builder, Schema\Complex::class); - - $operation = $builder->addOperation('get', 'GET', '/foo/:name/:type', 200, $complex); - $operation->setDescription('Returns a collection'); - $operation->setTags(['foo']); - $operation->setSecurity(['foo']); - $operation->addArgument('name', 'path', TypeFactory::getString()); - $operation->addArgument('type', 'path', TypeFactory::getString()); - $operation->addArgument('payload', 'body', $complex); + $operation->addArgument('payload', 'body', PropertyTypeFactory::getReference($create)); return $builder->getSpecification(); } @@ -171,57 +150,57 @@ protected function getSpecificationTest(): SpecificationInterface $testRequest = $this->addSchema($builder, Schema\TestRequest::class); $testResponse = $this->addSchema($builder, Schema\TestResponse::class); - $operation = $builder->addOperation('product.getAll', 'GET', '/anything', 200, $testResponse); + $operation = $builder->addOperation('product.getAll', 'GET', '/anything', 200, PropertyTypeFactory::getReference($testResponse)); $operation->setDescription('Returns a collection'); - $operation->addArgument('startIndex', 'query', TypeFactory::getInteger()); - $operation->addArgument('count', 'query', TypeFactory::getInteger()); - $operation->addArgument('search', 'query', TypeFactory::getString()); + $operation->addArgument('startIndex', 'query', PropertyTypeFactory::getInteger()); + $operation->addArgument('count', 'query', PropertyTypeFactory::getInteger()); + $operation->addArgument('search', 'query', PropertyTypeFactory::getString()); - $operation = $builder->addOperation('product.create', 'POST', '/anything', 200, $testResponse); + $operation = $builder->addOperation('product.create', 'POST', '/anything', 200, PropertyTypeFactory::getReference($testResponse)); $operation->setDescription('Creates a new product'); - $operation->addArgument('payload', 'body', $testRequest); - $operation->addThrow(500, $testResponse); + $operation->addArgument('payload', 'body', PropertyTypeFactory::getReference($testRequest)); + $operation->addThrow(500, PropertyTypeFactory::getReference($testResponse)); - $operation = $builder->addOperation('product.update', 'PUT', '/anything/:id', 200, $testResponse); + $operation = $builder->addOperation('product.update', 'PUT', '/anything/:id', 200, PropertyTypeFactory::getReference($testResponse)); $operation->setDescription('Updates an existing product'); - $operation->addArgument('id', 'path', TypeFactory::getInteger()); - $operation->addArgument('payload', 'body', $testRequest); + $operation->addArgument('id', 'path', PropertyTypeFactory::getInteger()); + $operation->addArgument('payload', 'body', PropertyTypeFactory::getReference($testRequest)); - $operation = $builder->addOperation('product.patch', 'PATCH', '/anything/:id', 200, $testResponse); + $operation = $builder->addOperation('product.patch', 'PATCH', '/anything/:id', 200, PropertyTypeFactory::getReference($testResponse)); $operation->setDescription('Patches an existing product'); - $operation->addArgument('id', 'path', TypeFactory::getInteger()); - $operation->addArgument('payload', 'body', $testRequest); + $operation->addArgument('id', 'path', PropertyTypeFactory::getInteger()); + $operation->addArgument('payload', 'body', PropertyTypeFactory::getReference($testRequest)); - $operation = $builder->addOperation('product.delete', 'DELETE', '/anything/:id', 200, $testResponse); + $operation = $builder->addOperation('product.delete', 'DELETE', '/anything/:id', 200, PropertyTypeFactory::getReference($testResponse)); $operation->setDescription('Deletes an existing product'); - $operation->addArgument('id', 'path', TypeFactory::getInteger()); + $operation->addArgument('id', 'path', PropertyTypeFactory::getInteger()); - $operation = $builder->addOperation('product.binary', 'POST', '/anything/binary', 200, $testResponse); + $operation = $builder->addOperation('product.binary', 'POST', '/anything/binary', 200, PropertyTypeFactory::getReference($testResponse)); $operation->setDescription('Test binary content type'); $operation->addArgument('payload', 'body', new ContentType(ContentType::BINARY)); $operation->addThrow(500, new ContentType(ContentType::BINARY)); - $operation = $builder->addOperation('product.form', 'POST', '/anything/form', 200, $testResponse); + $operation = $builder->addOperation('product.form', 'POST', '/anything/form', 200, PropertyTypeFactory::getReference($testResponse)); $operation->setDescription('Test form content type'); $operation->addArgument('payload', 'body', new ContentType(ContentType::FORM)); $operation->addThrow(500, new ContentType(ContentType::FORM)); - $operation = $builder->addOperation('product.json', 'POST', '/anything/json', 200, $testResponse); + $operation = $builder->addOperation('product.json', 'POST', '/anything/json', 200, PropertyTypeFactory::getReference($testResponse)); $operation->setDescription('Test json content type'); $operation->addArgument('payload', 'body', new ContentType(ContentType::JSON)); $operation->addThrow(500, new ContentType(ContentType::JSON)); - $operation = $builder->addOperation('product.multipart', 'POST', '/anything/multipart', 200, $testResponse); + $operation = $builder->addOperation('product.multipart', 'POST', '/anything/multipart', 200, PropertyTypeFactory::getReference($testResponse)); $operation->setDescription('Test json content type'); $operation->addArgument('payload', 'body', new ContentType(ContentType::MULTIPART)); $operation->addThrow(500, new ContentType(ContentType::MULTIPART)); - $operation = $builder->addOperation('product.text', 'POST', '/anything/text', 200, $testResponse); + $operation = $builder->addOperation('product.text', 'POST', '/anything/text', 200, PropertyTypeFactory::getReference($testResponse)); $operation->setDescription('Test text content type'); $operation->addArgument('payload', 'body', new ContentType(ContentType::TEXT)); $operation->addThrow(500, new ContentType(ContentType::TEXT)); - $operation = $builder->addOperation('product.xml', 'POST', '/anything/xml', 200, $testResponse); + $operation = $builder->addOperation('product.xml', 'POST', '/anything/xml', 200, PropertyTypeFactory::getReference($testResponse)); $operation->setDescription('Test xml content type'); $operation->addArgument('payload', 'body', new ContentType(ContentType::XML)); $operation->addThrow(500, new ContentType(ContentType::XML)); @@ -265,13 +244,13 @@ protected function getSpecificationImport(): SpecificationInterface $builder = $this->apiManager->getBuilder(); $definitions = new Definitions(); - $definitions->addType('import:my_type', TypeFactory::getStruct()->addProperty('foo', TypeFactory::getString())); - $definitions->addType('my_schema', TypeFactory::getStruct()->addProperty('foo', TypeFactory::getReference('import:my_type'))); + $definitions->addType('import:my_type', DefinitionTypeFactory::getStruct()->addProperty('foo', PropertyTypeFactory::getString())); + $definitions->addType('my_schema', DefinitionTypeFactory::getStruct()->addProperty('foo', PropertyTypeFactory::getReference('import:my_type'))); $builder->addDefinitions($definitions); - $operation = $builder->addOperation('foo', 'GET', '/anything', 200, TypeFactory::getReference('import:my_type')); - $operation->addArgument('body', 'body', TypeFactory::getReference('import:my_type')); - $operation->addThrow(500, TypeFactory::getReference('import:my_type')); + $operation = $builder->addOperation('foo', 'GET', '/anything', 200, PropertyTypeFactory::getReference('import:my_type')); + $operation->addArgument('body', 'body', PropertyTypeFactory::getReference('import:my_type')); + $operation->addThrow(500, PropertyTypeFactory::getReference('import:my_type')); return $builder->getSpecification(); } @@ -286,10 +265,10 @@ protected function writeChunksToFolder(Chunks $result, string $target): void iterator_to_array($result->writeToFolder($target)); } - private function addSchema(SpecificationBuilderInterface $builder, string $schema): TypeInterface + private function addSchema(SpecificationBuilderInterface $builder, string $schema): string { $result = $this->schemaManager->getSchema($schema); $builder->addDefinitions($result->getDefinitions()); - return $result->getType(); + return $result->getRoot(); } } diff --git a/tests/Generator/Markup/resource/client.md b/tests/Generator/Markup/resource/client.md index 5d0d879..bc01d9d 100644 --- a/tests/Generator/Markup/resource/client.md +++ b/tests/Generator/Markup/resource/client.md @@ -1,50 +1,50 @@ const client = new Client() client.get(name: string, type: string, startIndex: number, float: number, boolean: boolean, date: string, datetime: string, args: Entry): EntryCollection client.create(name: string, type: string, payload: EntryCreate): EntryMessage throws EntryMessage -client.update(name: string, type: string, payload: Record): Record throws EntryMessage, Record +client.update(name: string, type: string, payload: Map): Map throws EntryMessage, Map client.delete(name: string, type: string): void client.patch(name: string, type: string, payload: Array): Array throws EntryMessage, Array -interface EntryCollection { +export class EntryCollection { entry?: Array } -interface Entry { +export class Entry { id?: number userId?: number title?: string date?: string } -interface EntryMessage { +export class EntryMessage { success?: boolean message?: string } -interface EntryCreate { +export class EntryCreate { id?: number userId?: number - title: string - date: string + title?: string + date?: string } -interface EntryUpdate { - id: number +export class EntryUpdate { + id?: number userId?: number title?: string date?: string } -interface EntryDelete { - id: number +export class EntryDelete { + id?: number userId?: number title?: string date?: string } -interface EntryPatch { - id: number +export class EntryPatch { + id?: number userId?: number title?: string date?: string diff --git a/tests/Generator/Markup/resource/client_collection.md b/tests/Generator/Markup/resource/client_collection.md index 67a81c3..070c62e 100644 --- a/tests/Generator/Markup/resource/client_collection.md +++ b/tests/Generator/Markup/resource/client_collection.md @@ -7,25 +7,25 @@ client.bar().find(foo: string): EntryCollection client.bar().put(payload: EntryCreate): EntryMessage -interface EntryCollection { +export class EntryCollection { entry?: Array } -interface Entry { +export class Entry { id?: number userId?: number title?: string date?: string } -interface EntryMessage { +export class EntryMessage { success?: boolean message?: string } -interface EntryCreate { +export class EntryCreate { id?: number userId?: number - title: string - date: string + title?: string + date?: string } diff --git a/tests/Generator/Markup/resource/html.htm b/tests/Generator/Markup/resource/html.htm index b521927..d0fcebc 100644 --- a/tests/Generator/Markup/resource/html.htm +++ b/tests/Generator/Markup/resource/html.htm @@ -6,44 +6,44 @@

EntryCollection

{
   "entry": Array (Entry),
-}
FieldDescription
entryArray (Entry)
+}
FieldDescription
entryArray (Entry)

Entry

{
   "id": Integer,
   "userId": Integer,
   "title": String,
   "date": String (date-time),
-}
FieldDescription
idInteger
userIdInteger
titleString
MinLength
3
MaxLength
16
Pattern
[A-z]+
dateString (date-time)
+}
FieldDescription
idInteger
userIdInteger
titleString
dateString (date-time)

EntryMessage

{
   "success": Boolean,
   "message": String,
-}
FieldDescription
successBoolean
messageString
+}
FieldDescription
successBoolean
messageString

EntryCreate

{
   "id": Integer,
   "userId": Integer,
   "title": String,
   "date": String (date-time),
-}
FieldDescription
idInteger
userIdInteger
titleString
MinLength
3
MaxLength
16
Pattern
[A-z]+
dateString (date-time)
+}
FieldDescription
idInteger
userIdInteger
titleString
dateString (date-time)

EntryUpdate

{
   "id": Integer,
   "userId": Integer,
   "title": String,
   "date": String (date-time),
-}
FieldDescription
idInteger
userIdInteger
titleString
MinLength
3
MaxLength
16
Pattern
[A-z]+
dateString (date-time)
+}
FieldDescription
idInteger
userIdInteger
titleString
dateString (date-time)

EntryDelete

{
   "id": Integer,
   "userId": Integer,
   "title": String,
   "date": String (date-time),
-}
FieldDescription
idInteger
userIdInteger
titleString
MinLength
3
MaxLength
16
Pattern
[A-z]+
dateString (date-time)
+}
FieldDescription
idInteger
userIdInteger
titleString
dateString (date-time)

EntryPatch

{
   "id": Integer,
   "userId": Integer,
   "title": String,
   "date": String (date-time),
-}
FieldDescription
idInteger
userIdInteger
titleString
MinLength
3
MaxLength
16
Pattern
[A-z]+
dateString (date-time)
+}
FieldDescription
idInteger
userIdInteger
titleString
dateString (date-time)
diff --git a/tests/Generator/Markup/resource/markdown.md b/tests/Generator/Markup/resource/markdown.md index 117e6f1..7ae4f31 100644 --- a/tests/Generator/Markup/resource/markdown.md +++ b/tests/Generator/Markup/resource/markdown.md @@ -62,44 +62,44 @@

EntryCollection

{
   "entry": Array (Entry),
-}
FieldDescription
entryArray (Entry)
+}
FieldDescription
entryArray (Entry)

Entry

{
   "id": Integer,
   "userId": Integer,
   "title": String,
   "date": String (date-time),
-}
FieldDescription
idInteger
userIdInteger
titleString
MinLength
3
MaxLength
16
Pattern
[A-z]+
dateString (date-time)
+}
FieldDescription
idInteger
userIdInteger
titleString
dateString (date-time)

EntryMessage

{
   "success": Boolean,
   "message": String,
-}
FieldDescription
successBoolean
messageString
+}
FieldDescription
successBoolean
messageString

EntryCreate

{
   "id": Integer,
   "userId": Integer,
   "title": String,
   "date": String (date-time),
-}
FieldDescription
idInteger
userIdInteger
titleString
MinLength
3
MaxLength
16
Pattern
[A-z]+
dateString (date-time)
+}
FieldDescription
idInteger
userIdInteger
titleString
dateString (date-time)

EntryUpdate

{
   "id": Integer,
   "userId": Integer,
   "title": String,
   "date": String (date-time),
-}
FieldDescription
idInteger
userIdInteger
titleString
MinLength
3
MaxLength
16
Pattern
[A-z]+
dateString (date-time)
+}
FieldDescription
idInteger
userIdInteger
titleString
dateString (date-time)

EntryDelete

{
   "id": Integer,
   "userId": Integer,
   "title": String,
   "date": String (date-time),
-}
FieldDescription
idInteger
userIdInteger
titleString
MinLength
3
MaxLength
16
Pattern
[A-z]+
dateString (date-time)
+}
FieldDescription
idInteger
userIdInteger
titleString
dateString (date-time)

EntryPatch

{
   "id": Integer,
   "userId": Integer,
   "title": String,
   "date": String (date-time),
-}
FieldDescription
idInteger
userIdInteger
titleString
MinLength
3
MaxLength
16
Pattern
[A-z]+
dateString (date-time)
+}
FieldDescription
idInteger
userIdInteger
titleString
dateString (date-time)
diff --git a/tests/Generator/Schema/Complex.php b/tests/Generator/Schema/Complex.php deleted file mode 100644 index b3c31da..0000000 --- a/tests/Generator/Schema/Complex.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * Copyright (c) Christoph Kappestein - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -namespace PSX\Api\Tests\Generator\Schema; - -use PSX\Schema\SchemaAbstract; -use PSX\Schema\TypeFactory; - -/** - * Complex - * - * @author Christoph Kappestein - * @license http://www.apache.org/licenses/LICENSE-2.0 - * @link https://phpsx.org - */ -class Complex extends SchemaAbstract -{ - public function build(): void - { - $this->add('EntryOrMessage', TypeFactory::getUnion([ - $this->get(Entry::class), - $this->get(Message::class) - ])); - - $this->setRoot('EntryOrMessage'); - } -} diff --git a/tests/Generator/Schema/Create.php b/tests/Generator/Schema/Create.php index 23930a3..c2e0dcb 100644 --- a/tests/Generator/Schema/Create.php +++ b/tests/Generator/Schema/Create.php @@ -33,7 +33,6 @@ class Create extends SchemaAbstract { public function build(): void { - $entry = $this->modify(Entry::class, 'EntryCreate'); - $entry->setRequired(['title', 'date']); + $this->modify(Entry::class, 'EntryCreate'); } } diff --git a/tests/Generator/Schema/Delete.php b/tests/Generator/Schema/Delete.php index 60ddee8..bd73ded 100644 --- a/tests/Generator/Schema/Delete.php +++ b/tests/Generator/Schema/Delete.php @@ -33,7 +33,6 @@ class Delete extends SchemaAbstract { public function build(): void { - $entry = $this->modify(Entry::class, 'EntryDelete'); - $entry->setRequired(['id']); + $this->modify(Entry::class, 'EntryDelete'); } } diff --git a/tests/Generator/Schema/Entry.php b/tests/Generator/Schema/Entry.php index bf6bc89..8fcb6b8 100644 --- a/tests/Generator/Schema/Entry.php +++ b/tests/Generator/Schema/Entry.php @@ -36,10 +36,7 @@ public function build(): void $type = $this->newStruct('Entry'); $type->addInteger('id'); $type->addInteger('userId'); - $type->addString('title') - ->setMinLength(3) - ->setMaxLength(16) - ->setPattern('[A-z]+'); + $type->addString('title'); $type->addDateTime('date'); } } diff --git a/tests/Generator/Schema/Patch.php b/tests/Generator/Schema/Patch.php index 65d14ca..0b6d92e 100644 --- a/tests/Generator/Schema/Patch.php +++ b/tests/Generator/Schema/Patch.php @@ -33,7 +33,6 @@ class Patch extends SchemaAbstract { public function build(): void { - $entry = $this->modify(Entry::class, 'EntryPatch'); - $entry->setRequired(['id']); + $this->modify(Entry::class, 'EntryPatch'); } } diff --git a/tests/Generator/Schema/Update.php b/tests/Generator/Schema/Update.php index 1f2f241..7f05a40 100644 --- a/tests/Generator/Schema/Update.php +++ b/tests/Generator/Schema/Update.php @@ -33,7 +33,6 @@ class Update extends SchemaAbstract { public function build(): void { - $entry = $this->modify(Entry::class, 'EntryUpdate'); - $entry->setRequired(['id']); + $this->modify(Entry::class, 'EntryUpdate'); } } diff --git a/tests/Generator/Server/resource/php/src/Model/Entry.php b/tests/Generator/Server/resource/php/src/Model/Entry.php index e9ee19f..339fb38 100644 --- a/tests/Generator/Server/resource/php/src/Model/Entry.php +++ b/tests/Generator/Server/resource/php/src/Model/Entry.php @@ -6,17 +6,11 @@ namespace App\Model; -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; class Entry implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Server/resource/php/src/Model/EntryCreate.php b/tests/Generator/Server/resource/php/src/Model/EntryCreate.php index dda752c..036bc57 100644 --- a/tests/Generator/Server/resource/php/src/Model/EntryCreate.php +++ b/tests/Generator/Server/resource/php/src/Model/EntryCreate.php @@ -6,19 +6,11 @@ namespace App\Model; -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; -use PSX\Schema\Attribute\Required; -#[Required(array('title', 'date'))] class EntryCreate implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Server/resource/php/src/Model/EntryDelete.php b/tests/Generator/Server/resource/php/src/Model/EntryDelete.php index 2422a5d..96dec14 100644 --- a/tests/Generator/Server/resource/php/src/Model/EntryDelete.php +++ b/tests/Generator/Server/resource/php/src/Model/EntryDelete.php @@ -6,19 +6,11 @@ namespace App\Model; -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; -use PSX\Schema\Attribute\Required; -#[Required(array('id'))] class EntryDelete implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Server/resource/php/src/Model/EntryPatch.php b/tests/Generator/Server/resource/php/src/Model/EntryPatch.php index d403db4..d189fed 100644 --- a/tests/Generator/Server/resource/php/src/Model/EntryPatch.php +++ b/tests/Generator/Server/resource/php/src/Model/EntryPatch.php @@ -6,19 +6,11 @@ namespace App\Model; -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; -use PSX\Schema\Attribute\Required; -#[Required(array('id'))] class EntryPatch implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Server/resource/php/src/Model/EntryUpdate.php b/tests/Generator/Server/resource/php/src/Model/EntryUpdate.php index 0b22eb6..84a51cb 100644 --- a/tests/Generator/Server/resource/php/src/Model/EntryUpdate.php +++ b/tests/Generator/Server/resource/php/src/Model/EntryUpdate.php @@ -6,19 +6,11 @@ namespace App\Model; -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; -use PSX\Schema\Attribute\Required; -#[Required(array('id'))] class EntryUpdate implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Server/resource/php_complex/src/Model/Entry.php b/tests/Generator/Server/resource/php_complex/src/Model/Entry.php index e9ee19f..339fb38 100644 --- a/tests/Generator/Server/resource/php_complex/src/Model/Entry.php +++ b/tests/Generator/Server/resource/php_complex/src/Model/Entry.php @@ -6,17 +6,11 @@ namespace App\Model; -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; class Entry implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Server/resource/php_complex/src/Model/EntryCreate.php b/tests/Generator/Server/resource/php_complex/src/Model/EntryCreate.php index dda752c..036bc57 100644 --- a/tests/Generator/Server/resource/php_complex/src/Model/EntryCreate.php +++ b/tests/Generator/Server/resource/php_complex/src/Model/EntryCreate.php @@ -6,19 +6,11 @@ namespace App\Model; -use PSX\Schema\Attribute\MaxLength; -use PSX\Schema\Attribute\MinLength; -use PSX\Schema\Attribute\Pattern; -use PSX\Schema\Attribute\Required; -#[Required(array('title', 'date'))] class EntryCreate implements \JsonSerializable, \PSX\Record\RecordableInterface { protected ?int $id = null; protected ?int $userId = null; - #[Pattern('[A-z]+')] - #[MinLength(3)] - #[MaxLength(16)] protected ?string $title = null; protected ?\PSX\DateTime\LocalDateTime $date = null; public function setId(?int $id) : void diff --git a/tests/Generator/Server/resource/typescript/src/controller/app.controller.ts b/tests/Generator/Server/resource/typescript/src/controller/app.controller.ts index 6c1de0a..0bd2d24 100644 --- a/tests/Generator/Server/resource/typescript/src/controller/app.controller.ts +++ b/tests/Generator/Server/resource/typescript/src/controller/app.controller.ts @@ -30,7 +30,7 @@ export class AppController { @Put('/foo/:name/:type') @HttpCode(200) - update(@Param('name') name: string, @Param('type') type: string, @Body() payload: Record): Record { + update(@Param('name') name: string, @Param('type') type: string, @Body() payload: Map): Map { // @TODO implement method return {}; } diff --git a/tests/Generator/Server/resource/typescript/src/dto/Entry.ts b/tests/Generator/Server/resource/typescript/src/dto/Entry.ts index b50aaa0..9cd75df 100644 --- a/tests/Generator/Server/resource/typescript/src/dto/Entry.ts +++ b/tests/Generator/Server/resource/typescript/src/dto/Entry.ts @@ -3,7 +3,7 @@ * {@link https://sdkgen.app} */ -export interface Entry { +export class Entry { id?: number userId?: number title?: string diff --git a/tests/Generator/Server/resource/typescript/src/dto/EntryCollection.ts b/tests/Generator/Server/resource/typescript/src/dto/EntryCollection.ts index 1f8e50b..b7893c5 100644 --- a/tests/Generator/Server/resource/typescript/src/dto/EntryCollection.ts +++ b/tests/Generator/Server/resource/typescript/src/dto/EntryCollection.ts @@ -4,6 +4,6 @@ */ import {Entry} from "./Entry"; -export interface EntryCollection { +export class EntryCollection { entry?: Array } diff --git a/tests/Generator/Server/resource/typescript/src/dto/EntryCreate.ts b/tests/Generator/Server/resource/typescript/src/dto/EntryCreate.ts index ec66486..ba35a58 100644 --- a/tests/Generator/Server/resource/typescript/src/dto/EntryCreate.ts +++ b/tests/Generator/Server/resource/typescript/src/dto/EntryCreate.ts @@ -3,9 +3,9 @@ * {@link https://sdkgen.app} */ -export interface EntryCreate { +export class EntryCreate { id?: number userId?: number - title: string - date: string + title?: string + date?: string } diff --git a/tests/Generator/Server/resource/typescript/src/dto/EntryDelete.ts b/tests/Generator/Server/resource/typescript/src/dto/EntryDelete.ts index 102bbf9..2b48203 100644 --- a/tests/Generator/Server/resource/typescript/src/dto/EntryDelete.ts +++ b/tests/Generator/Server/resource/typescript/src/dto/EntryDelete.ts @@ -3,8 +3,8 @@ * {@link https://sdkgen.app} */ -export interface EntryDelete { - id: number +export class EntryDelete { + id?: number userId?: number title?: string date?: string diff --git a/tests/Generator/Server/resource/typescript/src/dto/EntryMessage.ts b/tests/Generator/Server/resource/typescript/src/dto/EntryMessage.ts index 3c733c2..eecb5a7 100644 --- a/tests/Generator/Server/resource/typescript/src/dto/EntryMessage.ts +++ b/tests/Generator/Server/resource/typescript/src/dto/EntryMessage.ts @@ -3,7 +3,7 @@ * {@link https://sdkgen.app} */ -export interface EntryMessage { +export class EntryMessage { success?: boolean message?: string } diff --git a/tests/Generator/Server/resource/typescript/src/dto/EntryPatch.ts b/tests/Generator/Server/resource/typescript/src/dto/EntryPatch.ts index d901ed0..8be6551 100644 --- a/tests/Generator/Server/resource/typescript/src/dto/EntryPatch.ts +++ b/tests/Generator/Server/resource/typescript/src/dto/EntryPatch.ts @@ -3,8 +3,8 @@ * {@link https://sdkgen.app} */ -export interface EntryPatch { - id: number +export class EntryPatch { + id?: number userId?: number title?: string date?: string diff --git a/tests/Generator/Server/resource/typescript/src/dto/EntryUpdate.ts b/tests/Generator/Server/resource/typescript/src/dto/EntryUpdate.ts index 984816c..92b8893 100644 --- a/tests/Generator/Server/resource/typescript/src/dto/EntryUpdate.ts +++ b/tests/Generator/Server/resource/typescript/src/dto/EntryUpdate.ts @@ -3,8 +3,8 @@ * {@link https://sdkgen.app} */ -export interface EntryUpdate { - id: number +export class EntryUpdate { + id?: number userId?: number title?: string date?: string diff --git a/tests/Generator/Server/resource/typescript_complex/src/dto/Entry.ts b/tests/Generator/Server/resource/typescript_complex/src/dto/Entry.ts index b50aaa0..9cd75df 100644 --- a/tests/Generator/Server/resource/typescript_complex/src/dto/Entry.ts +++ b/tests/Generator/Server/resource/typescript_complex/src/dto/Entry.ts @@ -3,7 +3,7 @@ * {@link https://sdkgen.app} */ -export interface Entry { +export class Entry { id?: number userId?: number title?: string diff --git a/tests/Generator/Server/resource/typescript_complex/src/dto/EntryCollection.ts b/tests/Generator/Server/resource/typescript_complex/src/dto/EntryCollection.ts index 1f8e50b..b7893c5 100644 --- a/tests/Generator/Server/resource/typescript_complex/src/dto/EntryCollection.ts +++ b/tests/Generator/Server/resource/typescript_complex/src/dto/EntryCollection.ts @@ -4,6 +4,6 @@ */ import {Entry} from "./Entry"; -export interface EntryCollection { +export class EntryCollection { entry?: Array } diff --git a/tests/Generator/Server/resource/typescript_complex/src/dto/EntryCreate.ts b/tests/Generator/Server/resource/typescript_complex/src/dto/EntryCreate.ts index ec66486..ba35a58 100644 --- a/tests/Generator/Server/resource/typescript_complex/src/dto/EntryCreate.ts +++ b/tests/Generator/Server/resource/typescript_complex/src/dto/EntryCreate.ts @@ -3,9 +3,9 @@ * {@link https://sdkgen.app} */ -export interface EntryCreate { +export class EntryCreate { id?: number userId?: number - title: string - date: string + title?: string + date?: string } diff --git a/tests/Generator/Server/resource/typescript_complex/src/dto/EntryMessage.ts b/tests/Generator/Server/resource/typescript_complex/src/dto/EntryMessage.ts index 3c733c2..eecb5a7 100644 --- a/tests/Generator/Server/resource/typescript_complex/src/dto/EntryMessage.ts +++ b/tests/Generator/Server/resource/typescript_complex/src/dto/EntryMessage.ts @@ -3,7 +3,7 @@ * {@link https://sdkgen.app} */ -export interface EntryMessage { +export class EntryMessage { success?: boolean message?: string } diff --git a/tests/Generator/Spec/OpenAPITest.php b/tests/Generator/Spec/OpenAPITest.php index c2662b7..39bdfdd 100644 --- a/tests/Generator/Spec/OpenAPITest.php +++ b/tests/Generator/Spec/OpenAPITest.php @@ -44,16 +44,6 @@ public function testGenerate() } public function testGenerateAll() - { - $generator = new OpenAPI(1, 'http://api.phpsx.org'); - - $actual = $generator->generate($this->getSpecificationCollection()); - $expect = file_get_contents(__DIR__ . '/resource/openapi_collection.json'); - - $this->assertJsonStringEqualsJsonString($expect, $actual, $actual); - } - - public function testGenerateComplex() { $generator = new OpenAPI(1, 'http://api.phpsx.org'); $generator->setTitle('Sample Pet Store App'); @@ -68,8 +58,8 @@ public function testGenerateComplex() $generator->addTag('foo', 'Foo tag'); $generator->addTag('bar', 'Boo tag'); - $actual = $generator->generate($this->getSpecificationComplex()); - $expect = file_get_contents(__DIR__ . '/resource/openapi_complex.json'); + $actual = $generator->generate($this->getSpecificationCollection()); + $expect = file_get_contents(__DIR__ . '/resource/openapi_collection.json'); $this->assertJsonStringEqualsJsonString($expect, $actual, $actual); } diff --git a/tests/Generator/Spec/TypeAPITest.php b/tests/Generator/Spec/TypeAPITest.php index 950c392..8ca8f29 100644 --- a/tests/Generator/Spec/TypeAPITest.php +++ b/tests/Generator/Spec/TypeAPITest.php @@ -51,14 +51,4 @@ public function testGenerateAll() $this->assertJsonStringEqualsJsonString($expect, $actual, $actual); } - - public function testGenerateComplex() - { - $generator = new TypeAPI(); - - $actual = $generator->generate($this->getSpecificationComplex()); - $expect = file_get_contents(__DIR__ . '/resource/typeapi_complex.json'); - - $this->assertJsonStringEqualsJsonString($expect, $actual, $actual); - } } diff --git a/tests/Generator/Spec/resource/openapi.json b/tests/Generator/Spec/resource/openapi.json index c171cc7..531e293 100644 --- a/tests/Generator/Spec/resource/openapi.json +++ b/tests/Generator/Spec/resource/openapi.json @@ -22,9 +22,7 @@ "required": false, "schema": { "description": "startIndex parameter", - "type": "integer", - "minimum": 0, - "maximum": 32 + "type": "integer" } }, { @@ -48,8 +46,8 @@ "in": "query", "required": false, "schema": { - "format": "date", - "type": "string" + "type": "string", + "format": "date" } }, { @@ -57,8 +55,8 @@ "in": "query", "required": false, "schema": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } }, { @@ -289,14 +287,11 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } } }, @@ -321,20 +316,13 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } - }, - "required": [ - "title", - "date" - ] + } }, "EntryDelete": { "type": "object", @@ -346,19 +334,13 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } - }, - "required": [ - "id" - ] + } }, "EntryMessage": { "type": "object", @@ -381,19 +363,13 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } - }, - "required": [ - "id" - ] + } }, "EntryUpdate": { "type": "object", @@ -405,19 +381,13 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } - }, - "required": [ - "id" - ] + } } } } diff --git a/tests/Generator/Spec/resource/openapi_collection.json b/tests/Generator/Spec/resource/openapi_collection.json index a79e96c..3eca45b 100644 --- a/tests/Generator/Spec/resource/openapi_collection.json +++ b/tests/Generator/Spec/resource/openapi_collection.json @@ -1,7 +1,18 @@ { "openapi": "3.0.3", "info": { - "title": "PSX", + "title": "Sample Pet Store App", + "description": "This is a sample server for a pet store.", + "termsOfService": "http://example.com/terms/", + "contact": { + "name": "API Support", + "url": "http://www.example.com/support", + "email": "support@example.com" + }, + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + }, "version": "1" }, "servers": [ @@ -208,14 +219,11 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } } }, @@ -240,20 +248,13 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } - }, - "required": [ - "title", - "date" - ] + } }, "EntryMessage": { "type": "object", @@ -266,6 +267,31 @@ } } } + }, + "securitySchemes": { + "OAuth2": { + "type": "oauth2", + "flows": { + "authorizationCode": { + "authorizationUrl": "http://api.phpsx.org/authorization", + "tokenUrl": "http://api.phpsx.org/token", + "scopes": { + "foo": "Foo sope", + "bar": "Bar scope" + } + } + } + } + } + }, + "tags": [ + { + "name": "foo", + "description": "Foo tag" + }, + { + "name": "bar", + "description": "Boo tag" } - } + ] } \ No newline at end of file diff --git a/tests/Generator/Spec/resource/typeapi.json b/tests/Generator/Spec/resource/typeapi.json index 300a351..b40d3b0 100644 --- a/tests/Generator/Spec/resource/typeapi.json +++ b/tests/Generator/Spec/resource/typeapi.json @@ -9,7 +9,8 @@ "return": { "code": 200, "schema": { - "$ref": "EntryCollection" + "type": "reference", + "target": "EntryCollection" } }, "arguments": { @@ -17,19 +18,12 @@ "in": "path", "schema": { "description": "Name parameter", - "type": "string", - "pattern": "[A-z]+", - "minLength": 0, - "maxLength": 16 + "type": "string" } }, "type": { "in": "path", "schema": { - "enum": [ - "foo", - "bar" - ], "type": "string" } }, @@ -37,9 +31,7 @@ "in": "query", "schema": { "description": "startIndex parameter", - "type": "integer", - "minimum": 0, - "maximum": 32 + "type": "integer" } }, "float": { @@ -57,21 +49,22 @@ "date": { "in": "query", "schema": { - "format": "date", - "type": "string" + "type": "string", + "format": "date" } }, "datetime": { "in": "query", "schema": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } }, "args": { "in": "query", "schema": { - "$ref": "Entry" + "type": "reference", + "target": "Entry" } } }, @@ -88,7 +81,8 @@ "return": { "code": 201, "schema": { - "$ref": "EntryMessage" + "type": "reference", + "target": "EntryMessage" } }, "arguments": { @@ -107,7 +101,8 @@ "payload": { "in": "body", "schema": { - "$ref": "EntryCreate" + "type": "reference", + "target": "EntryCreate" } } }, @@ -115,13 +110,15 @@ { "code": 400, "schema": { - "$ref": "EntryMessage" + "type": "reference", + "target": "EntryMessage" } }, { "code": 500, "schema": { - "$ref": "EntryMessage" + "type": "reference", + "target": "EntryMessage" } } ], @@ -137,9 +134,10 @@ "return": { "code": 200, "schema": { - "type": "object", - "additionalProperties": { - "$ref": "EntryMessage" + "type": "map", + "schema": { + "type": "reference", + "target": "EntryMessage" } } }, @@ -159,9 +157,10 @@ "payload": { "in": "body", "schema": { - "type": "object", - "additionalProperties": { - "$ref": "EntryUpdate" + "type": "map", + "schema": { + "type": "reference", + "target": "EntryUpdate" } } } @@ -170,15 +169,17 @@ { "code": 400, "schema": { - "$ref": "EntryMessage" + "type": "reference", + "target": "EntryMessage" } }, { "code": 500, "schema": { - "type": "object", - "additionalProperties": { - "$ref": "EntryMessage" + "type": "map", + "schema": { + "type": "reference", + "target": "EntryMessage" } } } @@ -195,7 +196,8 @@ "return": { "code": 204, "schema": { - "$ref": "EntryMessage" + "type": "reference", + "target": "EntryMessage" } }, "arguments": { @@ -214,7 +216,8 @@ "payload": { "in": "body", "schema": { - "$ref": "EntryDelete" + "type": "reference", + "target": "EntryDelete" } } }, @@ -232,8 +235,9 @@ "code": 200, "schema": { "type": "array", - "items": { - "$ref": "EntryMessage" + "schema": { + "type": "reference", + "target": "EntryMessage" } } }, @@ -254,8 +258,9 @@ "in": "body", "schema": { "type": "array", - "items": { - "$ref": "EntryPatch" + "schema": { + "type": "reference", + "target": "EntryPatch" } } } @@ -264,15 +269,17 @@ { "code": 400, "schema": { - "$ref": "EntryMessage" + "type": "reference", + "target": "EntryMessage" } }, { "code": 500, "schema": { "type": "array", - "items": { - "$ref": "EntryMessage" + "schema": { + "type": "reference", + "target": "EntryMessage" } } } @@ -286,7 +293,7 @@ }, "definitions": { "Entry": { - "type": "object", + "type": "struct", "properties": { "id": { "type": "integer" @@ -295,30 +302,28 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } } }, "EntryCollection": { - "type": "object", + "type": "struct", "properties": { "entry": { "type": "array", - "items": { - "$ref": "Entry" + "schema": { + "type": "reference", + "target": "Entry" } } } }, "EntryCreate": { - "type": "object", + "type": "struct", "properties": { "id": { "type": "integer" @@ -327,23 +332,16 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } - }, - "required": [ - "title", - "date" - ] + } }, "EntryDelete": { - "type": "object", + "type": "struct", "properties": { "id": { "type": "integer" @@ -352,22 +350,16 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } - }, - "required": [ - "id" - ] + } }, "EntryMessage": { - "type": "object", + "type": "struct", "properties": { "success": { "type": "boolean" @@ -378,7 +370,7 @@ } }, "EntryPatch": { - "type": "object", + "type": "struct", "properties": { "id": { "type": "integer" @@ -387,22 +379,16 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } - }, - "required": [ - "id" - ] + } }, "EntryUpdate": { - "type": "object", + "type": "struct", "properties": { "id": { "type": "integer" @@ -411,19 +397,13 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } - }, - "required": [ - "id" - ] + } } } } \ No newline at end of file diff --git a/tests/Generator/Spec/resource/typeapi_collection.json b/tests/Generator/Spec/resource/typeapi_collection.json index dc0844b..9617bc6 100644 --- a/tests/Generator/Spec/resource/typeapi_collection.json +++ b/tests/Generator/Spec/resource/typeapi_collection.json @@ -9,7 +9,8 @@ "return": { "code": 200, "schema": { - "$ref": "EntryCollection" + "type": "reference", + "target": "EntryCollection" } }, "arguments": [], @@ -28,14 +29,16 @@ "return": { "code": 201, "schema": { - "$ref": "EntryMessage" + "type": "reference", + "target": "EntryMessage" } }, "arguments": { "payload": { "in": "body", "schema": { - "$ref": "EntryCreate" + "type": "reference", + "target": "EntryCreate" } } }, @@ -43,13 +46,15 @@ { "code": 400, "schema": { - "$ref": "EntryMessage" + "type": "reference", + "target": "EntryMessage" } }, { "code": 500, "schema": { - "$ref": "EntryMessage" + "type": "reference", + "target": "EntryMessage" } } ], @@ -67,7 +72,8 @@ "return": { "code": 200, "schema": { - "$ref": "EntryCollection" + "type": "reference", + "target": "EntryCollection" } }, "arguments": { @@ -93,14 +99,16 @@ "return": { "code": 201, "schema": { - "$ref": "EntryMessage" + "type": "reference", + "target": "EntryMessage" } }, "arguments": { "payload": { "in": "body", "schema": { - "$ref": "EntryCreate" + "type": "reference", + "target": "EntryCreate" } } }, @@ -119,7 +127,8 @@ "return": { "code": 200, "schema": { - "$ref": "EntryCollection" + "type": "reference", + "target": "EntryCollection" } }, "arguments": { @@ -145,14 +154,16 @@ "return": { "code": 201, "schema": { - "$ref": "EntryMessage" + "type": "reference", + "target": "EntryMessage" } }, "arguments": { "payload": { "in": "body", "schema": { - "$ref": "EntryCreate" + "type": "reference", + "target": "EntryCreate" } } }, @@ -168,7 +179,7 @@ }, "definitions": { "Entry": { - "type": "object", + "type": "struct", "properties": { "id": { "type": "integer" @@ -177,30 +188,28 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } } }, "EntryCollection": { - "type": "object", + "type": "struct", "properties": { "entry": { "type": "array", - "items": { - "$ref": "Entry" + "schema": { + "type": "reference", + "target": "Entry" } } } }, "EntryCreate": { - "type": "object", + "type": "struct", "properties": { "id": { "type": "integer" @@ -209,23 +218,16 @@ "type": "integer" }, "title": { - "type": "string", - "pattern": "[A-z]+", - "minLength": 3, - "maxLength": 16 + "type": "string" }, "date": { - "format": "date-time", - "type": "string" + "type": "string", + "format": "date-time" } - }, - "required": [ - "title", - "date" - ] + } }, "EntryMessage": { - "type": "object", + "type": "struct", "properties": { "success": { "type": "boolean" diff --git a/tests/Inspector/ChangelogGeneratorTest.php b/tests/Inspector/ChangelogGeneratorTest.php index 7b64b23..44bf5c9 100644 --- a/tests/Inspector/ChangelogGeneratorTest.php +++ b/tests/Inspector/ChangelogGeneratorTest.php @@ -48,12 +48,12 @@ public function testGenerate() 'Operation "my.operation.get.method" has changed from "GET" to "PUT"', 'Operation "my.operation.get.path" has changed from "/my/endpoint" to "/my/endpoint/foo"', 'Operation "my.operation.get.return.code" has changed from "200" to "201"', - 'Type "my.operation.get.return" (reference) ref has changed from "Person" to "Message"', + 'Type "my.operation.get.return" (reference) target has changed from "Person" to "Message"', 'Operation "my.operation.get.arguments.id.in" has changed from "path" to "query"', 'Type "my.operation.get.arguments.id" (string) type has changed from "string" to "integer"', 'Operation "my.operation.get.arguments.search" was removed', 'Operation "my.operation.get.arguments.payload" was added', - 'Type "my.operation.get.throws.500" (reference) ref has changed from "Message" to "Person"', + 'Type "my.operation.get.throws.500" (reference) target has changed from "Message" to "Person"', 'Operation "my.operation.get.throws.400" was added', 'Operation "my.operation.get.description" has changed from "And a great description" to "And a great description foo"', 'Operation "my.operation.get.stability" has changed from "1" to "2"', @@ -87,12 +87,12 @@ public function testGenerateReverse() 'Operation "my.operation.get.method" has changed from "PUT" to "GET"', 'Operation "my.operation.get.path" has changed from "/my/endpoint/foo" to "/my/endpoint"', 'Operation "my.operation.get.return.code" has changed from "201" to "200"', - 'Type "my.operation.get.return" (reference) ref has changed from "Message" to "Person"', + 'Type "my.operation.get.return" (reference) target has changed from "Message" to "Person"', 'Operation "my.operation.get.arguments.id.in" has changed from "query" to "path"', 'Type "my.operation.get.arguments.id" (integer) type has changed from "integer" to "string"', 'Operation "my.operation.get.arguments.payload" was removed', 'Operation "my.operation.get.arguments.search" was added', - 'Type "my.operation.get.throws.500" (reference) ref has changed from "Person" to "Message"', + 'Type "my.operation.get.throws.500" (reference) target has changed from "Person" to "Message"', 'Operation "my.operation.get.throws.400" was removed', 'Operation "my.operation.get.description" has changed from "And a great description foo" to "And a great description"', 'Operation "my.operation.get.stability" has changed from "2" to "1"', diff --git a/tests/Parser/Attribute/TestController.php b/tests/Parser/Attribute/TestController.php index 140a4d9..c836bad 100644 --- a/tests/Parser/Attribute/TestController.php +++ b/tests/Parser/Attribute/TestController.php @@ -42,15 +42,15 @@ */ #[Description('Test description')] #[Path('/foo/:fooId')] -#[PathParam(name: 'fooId', type: Type::STRING, required: true)] +#[PathParam(name: 'fooId', type: Type::STRING)] class TestController { #[Get] #[Description('file://' . __DIR__ . '/description.md')] #[QueryParam(name: "foo", type: Type::STRING, description: "Test")] - #[QueryParam(name: "bar", type: Type::STRING, required: true)] - #[QueryParam(name: "baz", type: Type::STRING, enum: ["foo", "bar"])] - #[QueryParam(name: "boz", type: Type::STRING, pattern: "[A-z]+")] + #[QueryParam(name: "bar", type: Type::STRING)] + #[QueryParam(name: "baz", type: Type::STRING)] + #[QueryParam(name: "boz", type: Type::STRING)] #[QueryParam(name: "integer", type: Type::INTEGER)] #[QueryParam(name: "number", type: Type::NUMBER)] #[QueryParam(name: "date", type: Type::STRING, format: Format::DATETIME)] diff --git a/tests/Parser/AttributeTest.php b/tests/Parser/AttributeTest.php index 5a028ff..95f33d6 100644 --- a/tests/Parser/AttributeTest.php +++ b/tests/Parser/AttributeTest.php @@ -30,6 +30,7 @@ use PSX\Api\Tests\Parser\Attribute\PropertyController; use PSX\Api\Tests\Parser\Attribute\TestController; use PSX\Schema\ContentType; +use PSX\Schema\Type\Factory\PropertyTypeFactory; use PSX\Schema\TypeFactory; use Symfony\Component\Cache\Adapter\ArrayAdapter; @@ -67,13 +68,13 @@ public function testParseTypeHint() $this->assertInstanceOf(OperationInterface::class, $operation); $this->assertEquals('path', $operation->getArguments()->get('id')->getIn()); - $this->assertEquals(TypeFactory::getInteger(), $operation->getArguments()->get('id')->getSchema()); + $this->assertEquals(PropertyTypeFactory::getInteger(), $operation->getArguments()->get('id')->getSchema()); $this->assertEquals('query', $operation->getArguments()->get('year')->getIn()); - $this->assertEquals(TypeFactory::getString(), $operation->getArguments()->get('year')->getSchema()); + $this->assertEquals(PropertyTypeFactory::getString(), $operation->getArguments()->get('year')->getSchema()); $this->assertEquals('body', $operation->getArguments()->get('incoming')->getIn()); - $this->assertEquals(TypeFactory::getReference('Incoming'), $operation->getArguments()->get('incoming')->getSchema()); + $this->assertEquals(PropertyTypeFactory::getReference('Incoming'), $operation->getArguments()->get('incoming')->getSchema()); $this->assertEquals(200, $operation->getReturn()->getCode()); - $this->assertEquals(TypeFactory::getReference('Outgoing'), $operation->getReturn()->getSchema()); + $this->assertEquals(PropertyTypeFactory::getReference('Outgoing'), $operation->getReturn()->getSchema()); } public function testParseInvalid() diff --git a/tests/Parser/OpenAPITest.php b/tests/Parser/OpenAPITest.php index 328b466..3a565e3 100644 --- a/tests/Parser/OpenAPITest.php +++ b/tests/Parser/OpenAPITest.php @@ -23,6 +23,7 @@ use PSX\Api\OperationInterface; use PSX\Api\SpecificationInterface; use PSX\Schema\Format; +use PSX\Schema\Type\Factory\PropertyTypeFactory; use PSX\Schema\TypeFactory; /** @@ -55,26 +56,24 @@ public function testParsePetstore() $arguments = $operation->getArguments(); $this->assertEquals('query', $arguments->get('limit')->getIn()); - $this->assertEquals(['type' => 'integer', 'format' => Format::INT32, 'maximum' => 100], $arguments->get('limit')->getSchema()->toArray()); + $this->assertEquals(['type' => 'integer'], $arguments->get('limit')->getSchema()->toArray()); $this->assertEquals(200, $operation->getReturn()->getCode()); - $this->assertEquals(['$ref' => 'Pets'], $operation->getReturn()->getSchema()->toArray()); + $this->assertEquals(['type' => 'reference', 'target' => 'Pets'], $operation->getReturn()->getSchema()->toArray()); $this->assertCount(0, $operation->getThrows()); $this->assertEquals([ 'type' => 'array', - 'items' => TypeFactory::getReference('Pet'), - 'maxItems' => 100 + 'schema' => PropertyTypeFactory::getReference('Pet'), ], $definitions->getType('Pets')->toArray()); $this->assertEquals([ - 'type' => 'object', + 'type' => 'struct', 'properties' => [ - 'id' => TypeFactory::getInteger()->setFormat(Format::INT64), - 'name' => TypeFactory::getString(), - 'tag' => TypeFactory::getString() - ], - 'required' => ['id', 'name'] + 'id' => PropertyTypeFactory::getInteger(), + 'name' => PropertyTypeFactory::getString(), + 'tag' => PropertyTypeFactory::getString() + ] ], $definitions->getType('Pet')->toArray()); } diff --git a/tests/Parser/ParserTestCase.php b/tests/Parser/ParserTestCase.php index e4a278d..7f0c9b0 100644 --- a/tests/Parser/ParserTestCase.php +++ b/tests/Parser/ParserTestCase.php @@ -24,6 +24,7 @@ use PSX\Api\SpecificationInterface; use PSX\Api\Tests\ApiManagerTestCase; use PSX\Schema\Format; +use PSX\Schema\Type\Factory\PropertyTypeFactory; use PSX\Schema\TypeFactory; /** @@ -55,9 +56,9 @@ public function testParseSimple() $this->assertEquals('query', $arguments->get('bar')->getIn()); $this->assertEquals(['type' => 'string'], $arguments->get('bar')->getSchema()->toArray()); $this->assertEquals('query', $arguments->get('baz')->getIn()); - $this->assertEquals(['type' => 'string', 'enum' => ['foo', 'bar']], $arguments->get('baz')->getSchema()->toArray()); + $this->assertEquals(['type' => 'string'], $arguments->get('baz')->getSchema()->toArray()); $this->assertEquals('query', $arguments->get('boz')->getIn()); - $this->assertEquals(['type' => 'string', 'pattern' => '[A-z]+'], $arguments->get('boz')->getSchema()->toArray()); + $this->assertEquals(['type' => 'string'], $arguments->get('boz')->getSchema()->toArray()); $this->assertEquals('query', $arguments->get('integer')->getIn()); $this->assertEquals(['type' => 'integer'], $arguments->get('integer')->getSchema()->toArray()); $this->assertEquals('query', $arguments->get('number')->getIn()); @@ -69,37 +70,33 @@ public function testParseSimple() $this->assertEquals('query', $arguments->get('string')->getIn()); $this->assertEquals(['type' => 'string'], $arguments->get('string')->getSchema()->toArray()); $this->assertEquals('body', $arguments->get('payload')->getIn()); - $this->assertEquals(['$ref' => 'Song'], $arguments->get('payload')->getSchema()->toArray()); + $this->assertEquals(['type' => 'reference', 'target' => 'Song'], $arguments->get('payload')->getSchema()->toArray()); $this->assertEquals(200, $operation->getReturn()->getCode()); - $this->assertEquals(['$ref' => 'Song'], $operation->getReturn()->getSchema()->toArray()); + $this->assertEquals(['type' => 'reference', 'target' => 'Song'], $operation->getReturn()->getSchema()->toArray()); $this->assertCount(1, $operation->getThrows()); $this->assertEquals(500, $operation->getThrows()[0]->getCode()); - $this->assertEquals(['$ref' => 'Error'], $operation->getThrows()[0]->getSchema()->toArray()); + $this->assertEquals(['type' => 'reference', 'target' => 'Error'], $operation->getThrows()[0]->getSchema()->toArray()); $this->assertEquals([ 'description' => 'A canonical song', - 'type' => 'object', + 'type' => 'struct', 'properties' => [ - 'title' => TypeFactory::getString(), - 'artist' => TypeFactory::getString(), - 'length' => TypeFactory::getInteger(), - 'ratings' => TypeFactory::getArray(TypeFactory::getReference('Rating')), - ], - 'required' => ['title', 'artist'] + 'title' => PropertyTypeFactory::getString(), + 'artist' => PropertyTypeFactory::getString(), + 'length' => PropertyTypeFactory::getInteger(), + 'ratings' => PropertyTypeFactory::getArray(PropertyTypeFactory::getReference('Rating')), + ] ], $definitions->getType('Song')->toArray()); $this->assertEquals([ - 'type' => 'object', + 'type' => 'struct', 'properties' => [ - 'success' => TypeFactory::getBoolean(), - 'message' => TypeFactory::getString(), + 'success' => PropertyTypeFactory::getBoolean(), + 'message' => PropertyTypeFactory::getString(), ], ], $definitions->getType('Error')->toArray()); } - /** - * @return \PSX\Api\SpecificationInterface - */ abstract protected function getSpecification(): SpecificationInterface; }