dandoetech/openapi-generator

Generate OpenAPI 3.1 from DanDoeTech Resource Registry with optional model metadata fallback.

Maintainers

Package info

github.com/dandoetech/openapi-generator

pkg:composer/dandoetech/openapi-generator

Statistics

Installs: 0

Dependents: 2

Suggesters: 0

Stars: 0

Open Issues: 0

v0.2.0 2026-03-20 12:07 UTC

This package is auto-updated.

Last update: 2026-04-20 12:25:44 UTC


README

Pre-release — Architecture by senior tech lead, implementation largely AI-assisted with human review. Not fully reviewed. Architecture may change before v1.0.0.

Generate OpenAPI 3.1 specifications from a Resource Registry. Framework-agnostic — no Laravel required.

Installation

composer require dandoetech/openapi-generator

Requires dandoetech/resource-registry.

Quick Start

use DanDoeTech\ResourceRegistry\Registry\{ArrayRegistryDriver, Registry};
use DanDoeTech\ResourceRegistry\Definition\{FieldDefinition, FieldType, ActionDefinition};
use DanDoeTech\OpenApiGenerator\OpenApiGenerator;
use DanDoeTech\OpenApiGenerator\Support\ResourceResolver;

// Build a registry (or use class-based resources via laravel-resource-registry)
$registry = new Registry(new ArrayRegistryDriver([
    'product' => [
        'label' => 'Product',
        'fields' => [
            new FieldDefinition('id', FieldType::Integer, nullable: false),
            new FieldDefinition('name', FieldType::String, nullable: false),
            new FieldDefinition('price', FieldType::Float, nullable: false),
        ],
        'actions' => [new ActionDefinition('create')],
    ],
]));

// Generate the spec
$generator = new OpenApiGenerator(
    resolver: new ResourceResolver(),
    title: 'My API',
    version: '1.0.0',
);
$doc = $generator->generate($registry);

echo $doc->toJson();

Output (abbreviated):

{
  "openapi": "3.1.0",
  "info": { "title": "My API", "version": "1.0.0" },
  "paths": {
    "/product": {
      "get": { "summary": "List Product", "..." : "..." },
      "post": { "summary": "Create Product", "..." : "..." }
    },
    "/product/{id}": {
      "get": { "summary": "Fetch Product", "..." : "..." }
    }
  },
  "components": {
    "schemas": {
      "Product": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "format": "int64" },
          "name": { "type": "string" },
          "price": { "type": "number", "format": "double" }
        },
        "required": ["id", "name", "price"]
      },
      "ProblemJson": { "..." : "..." }
    }
  }
}

Laravel users: Use dandoetech/laravel-openapi-generator for Artisan commands and automatic registry binding.

API Overview

Class Purpose
OpenApiGenerator Main entry point — generate(Registry): OpenApiDocument
OpenApiDocument Result container — toArray() and toJson()
ResourceResolver Resolves fields from resource definitions with optional fallback
PathsBuilder Builds OpenAPI path items from resource definitions
ComponentsBuilder Builds component schemas from resource fields
SchemaFactory Maps fields and computed fields to JSON Schema properties
Types Maps FieldType enum to OpenAPI type/format pairs

Contracts

Interface Purpose
OpenApiGeneratorInterface generate(Registry): OpenApiDocument
ModelMetaProviderInterface Optional fallback for field metadata — fieldsFor(string $key): array

Type Mapping

FieldType OpenAPI
String { "type": "string" }
Integer { "type": "integer", "format": "int64" }
Float { "type": "number", "format": "double" }
Boolean { "type": "boolean" }
DateTime { "type": "string", "format": "date-time" }
Json { "type": "object" }
Date { "type": "string", "format": "date" }
Text { "type": "string" }
Email { "type": "string", "format": "email" }
Url { "type": "string", "format": "uri" }
Enum { "type": "string" }

Configuration

All configuration is via constructor arguments:

$generator = new OpenApiGenerator(
    resolver: new ResourceResolver($optionalFallbackProvider),
    title: 'My API',
    version: '2.0.0',
    servers: [['url' => 'https://api.example.com']],
);

Field Fallback

If a resource has no fields defined, the generator can fall back to a ModelMetaProviderInterface:

use DanDoeTech\OpenApiGenerator\ModelMeta\ArrayModelMetaProvider;

$fallback = new ArrayModelMetaProvider([
    'product' => [
        new FieldDefinition('id', FieldType::Integer, nullable: false),
        new FieldDefinition('name', FieldType::String, nullable: false),
    ],
]);
$resolver = new ResourceResolver($fallback);

Testing

composer install
composer test        # PHPUnit
composer qa          # cs:check + phpstan + test

License

MIT