Awesome-claude-code create-api-versioning

Generates API Versioning pattern for PHP 8.4. Creates version resolution strategies (URI prefix, Accept header, query parameter), middleware, and deprecation support. Includes unit tests.

install
source · Clone the upstream repo
git clone https://github.com/dykyi-roman/awesome-claude-code
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/dykyi-roman/awesome-claude-code "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/create-api-versioning" ~/.claude/skills/dykyi-roman-awesome-claude-code-create-api-versioning && rm -rf "$T"
manifest: skills/create-api-versioning/SKILL.md
source content

API Versioning Generator

Creates API Versioning infrastructure with multiple resolution strategies and deprecation support.

When to Use

ScenarioExample
Breaking API changesNew response format
Multiple API consumersMobile v1, web v2
Gradual migrationSunset old versions
Backward compatibilitySupport legacy clients

Component Characteristics

ApiVersion (Value Object)

  • Immutable version representation
  • Major and minor version numbers
  • Comparison methods (equals, greaterThan, lessThan)
  • String parsing (fromString "v1.2")

VersionResolverInterface

  • Extracts version from PSR-7 request
  • Returns null if version not found
  • Strategy pattern for different sources

Resolution Strategies

  • UriPrefixVersionResolver — Extracts from URI path (/v1/orders)
  • AcceptHeaderVersionResolver — Extracts from Accept header (application/vnd.api.v1+json)
  • QueryParamVersionResolver — Extracts from query string (?version=1)
  • CompositeVersionResolver — Tries multiple strategies in order

VersionMiddleware

  • PSR-15 middleware
  • Resolves version via strategy
  • Adds version to request attributes
  • Returns 400 if version required but missing

Generation Process

Step 1: Generate Domain Components

Path:

src/Domain/Shared/Api/

  1. ApiVersion.php
    — Immutable version value object
  2. VersionResolverInterface.php
    — Version resolution contract

Step 2: Generate Presentation Components

Path:

src/Presentation/Middleware/

  1. UriPrefixVersionResolver.php
    — URI path strategy
  2. AcceptHeaderVersionResolver.php
    — Content negotiation strategy
  3. QueryParamVersionResolver.php
    — Query parameter strategy
  4. CompositeVersionResolver.php
    — Composite strategy
  5. VersionMiddleware.php
    — PSR-15 middleware
  6. DeprecationHeaderMiddleware.php
    — Deprecation/Sunset headers

Step 3: Generate Tests

  1. ApiVersionTest.php
    — Value object tests
  2. UriPrefixVersionResolverTest.php
    — URI parsing tests
  3. AcceptHeaderVersionResolverTest.php
    — Header parsing tests
  4. VersionMiddlewareTest.php
    — Middleware behavior tests

File Placement

ComponentPath
ApiVersion
src/Domain/Shared/Api/
VersionResolverInterface
src/Domain/Shared/Api/
Resolvers
src/Presentation/Middleware/
Middleware
src/Presentation/Middleware/
Unit Tests
tests/Unit/

Naming Conventions

ComponentPatternExample
Version VO
ApiVersion
ApiVersion
Resolver Interface
VersionResolverInterface
VersionResolverInterface
Resolver
{Strategy}VersionResolver
UriPrefixVersionResolver
Composite
CompositeVersionResolver
CompositeVersionResolver
Middleware
VersionMiddleware
VersionMiddleware
Deprecation
DeprecationHeaderMiddleware
DeprecationHeaderMiddleware
Test
{ClassName}Test
ApiVersionTest

Quick Template Reference

ApiVersion

final readonly class ApiVersion
{
    public function __construct(
        public int $major,
        public int $minor = 0
    ) {
        if ($this->major < 1) {
            throw new \InvalidArgumentException('Major version must be at least 1');
        }
    }

    public static function fromString(string $version): self;
    public function toString(): string;
    public function equals(self $other): bool;
    public function greaterThan(self $other): bool;
}

VersionResolverInterface

interface VersionResolverInterface
{
    public function resolve(ServerRequestInterface $request): ?ApiVersion;
}

Usage Example

// Create composite resolver
$resolver = new CompositeVersionResolver([
    new UriPrefixVersionResolver(),
    new AcceptHeaderVersionResolver(),
    new QueryParamVersionResolver(),
]);

// Middleware adds version to request attributes
$middleware = new VersionMiddleware($resolver, defaultVersion: new ApiVersion(1));

// In action/controller
$version = $request->getAttribute('api_version');
if ($version->greaterThan(new ApiVersion(1))) {
    return $this->respondV2($data);
}

Strategy Comparison

StrategyURL ExampleProsCons
URI Prefix
/v1/orders
Explicit, cacheableURL changes per version
Accept Header
Accept: application/vnd.api.v1+json
Clean URLsComplex client setup
Query Param
/orders?version=1
Simple to testNot RESTful, caching issues

Anti-patterns to Avoid

Anti-patternProblemSolution
Version in BodyHard to routeUse URI/header/query
Unlimited VersionsMaintenance burdenDeprecation policy
No Default VersionBreaks existing clientsConfigure default
Breaking Without VersionClient disruptionAlways version breaking changes
No Deprecation NoticeSurprise removalDeprecation/Sunset headers
Copy-Paste ControllersDuplicated codeVersion-aware routing

References

For complete PHP templates and examples, see:

  • references/templates.md
    — ApiVersion, resolvers, middleware, deprecation templates
  • references/examples.md
    — Framework integration and tests