AgentSkillsCN

Api Versioning

API版本控制

SKILL.md

API Versioning

Skill Purpose: API version management, backward compatibility strategies, and version deprecation procedures


Core Skill Pattern

Objective: Establish robust API versioning strategy with backward compatibility, clear version communication, and smooth migration paths.

Universal Pattern:

  1. Define API versioning strategy and approach
  2. Create version identification and routing mechanisms
  3. Establish backward compatibility procedures
  4. Set up deprecation and sunset policies
  5. Create version migration and communication patterns

Key Decisions (Project-Specific):

  • Versioning approach (URL, header, or content negotiation)
  • Version format and numbering scheme
  • Backward compatibility duration and support level
  • Deprecation timeline and communication strategy
  • Migration assistance and documentation

Project-Specific Implementation Notes

Customize per project:

  • Versioning approach based on API complexity and client requirements
  • Support duration based on stability guarantees and SLA commitments
  • Migration strategy based on client impact and resources
  • Communication approach based on stakeholder needs
  • Documentation depth based on version complexity

Example Implementation (URI Versioning Pattern)

Note: This is an example pattern using URI-based versioning. Adapt versioning approach and implementation based on your specific API requirements and client needs.

Prerequisites (Example)

  • API endpoints established and documented
  • Client integration patterns identified
  • Versioning requirements and constraints defined
  • Backward compatibility needs assessed

Example: API Versioning Implementation

Framework-Specific Example: This demonstrates URI-based versioning with Next.js. Adapt for your versioning approach and framework requirements.

Version Structure

typescript
// lib/api-version.ts
export const API_VERSIONS = {
  V1: 'v1',
  V2: 'v2',
  CURRENT: 'v2',
  SUPPORTED: ['v1', 'v2'],
  DEPRECATED: [],
} as const;

export type ApiVersion = typeof API_VERSIONS[keyof typeof API_VERSIONS];

Version Middleware

typescript
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { API_VERSIONS } from './lib/api-version';

export function middleware(request: NextRequest) {
  const url = request.nextUrl;
  
  // Extract version from URL path
  const pathSegments = url.pathname.split('/');
  const versionSegment = pathSegments[1];
  
  // Validate version
  if (versionSegment.startsWith('v') && !API_VERSIONS.SUPPORTED.includes(versionSegment as any)) {
    return NextResponse.json(
      { error: 'Unsupported API version', supported: API_VERSIONS.SUPPORTED },
      { status: 400 }
    );
  }
  
  // Add version headers
  const response = NextResponse.next();
  response.headers.set('API-Version', API_VERSIONS.CURRENT);
  response.headers.set('API-Supported-Versions', API_VERSIONS.SUPPORTED.join(','));
  
  return response;
}

export const config = {
  matcher: ['/api/:path*'],
};

Versioned Route Structure

typescript
// app/api/v1/users/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: NextRequest) {
  // V1 implementation
  const users = [
    { id: 1, name: 'John Doe', email: 'john@example.com' }
  ];
  
  return NextResponse.json({ data: users });
}

export async function POST(request: NextRequest) {
  const body = await request.json();
  
  // V1 validation and creation logic
  const user = {
    id: Date.now(),
    name: body.name,
    email: body.email,
  };
  
  return NextResponse.json({ data: user }, { status: 201 });
}
typescript
// app/api/v2/users/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: NextRequest) {
  // V2 implementation with enhanced features
  const users = [
    { 
      id: 1, 
      name: 'John Doe', 
      email: 'john@example.com',
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString()
    }
  ];
  
  return NextResponse.json({ 
    data: users,
    meta: {
      total: users.length,
      version: 'v2'
    }
  });
}

export async function POST(request: NextRequest) {
  const body = await request.json();
  
  // V2 validation and creation with additional fields
  const user = {
    id: Date.now(),
    name: body.name,
    email: body.email,
    role: body.role || 'user',
    createdAt: new Date().toISOString(),
    updatedAt: new Date().toISOString(),
  };
  
  return NextResponse.json({ 
    data: user,
    meta: {
      version: 'v2'
    }
  }, { status: 201 });
}

Version Compatibility Layer

typescript
// lib/version-compatibility.ts
export class VersionCompatibility {
  static transformV1ToV2(v1Data: any): any {
    // Transform V1 format to V2 format
    return {
      ...v1Data,
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
    };
  }
  
  static transformV2ToV1(v2Data: any): any {
    // Transform V2 format to V1 format
    const { createdAt, updatedAt, ...v1Data } = v2Data;
    return v1Data;
  }
}

Deprecation Headers

typescript
// lib/deprecation-headers.ts
export function setDeprecationHeaders(response: NextResponse, version: string) {
  if (version === 'v1') {
    response.headers.set('Deprecation', 'true');
    response.headers.set('Sunset', '2024-12-31'); // Sunset date
    response.headers.set('Link', '</api/v2/users>; rel="successor-version"');
  }
}

Version Documentation

typescript
// app/api/versions/route.ts
import { NextResponse } from 'next/server';
import { API_VERSIONS } from '../../../lib/api-version';

export async function GET() {
  return NextResponse.json({
    current: API_VERSIONS.CURRENT,
    supported: API_VERSIONS.SUPPORTED,
    deprecated: API_VERSIONS.DEPRECATED,
    migration: {
      v1_to_v2: {
        guide: '/docs/migration/v1-to-v2',
        breaking_changes: [
          'Added createdAt and updatedAt fields',
          'Response structure includes meta object',
          'POST requests now accept optional role field'
        ],
        sunset_date: '2024-12-31'
      }
    }
  });
}

Best Practices

  1. Semantic versioning - Use clear version numbers that communicate compatibility
  2. Backward compatibility - Maintain support for existing clients during transition periods
  3. Clear communication - Provide advance notice of deprecations and breaking changes
  4. Migration assistance - Offer guides and tools to help clients upgrade
  5. Version sunset - Define clear timelines for removing old versions

Stop Conditions

STOP and escalate if:

  • Versioning strategy unclear or conflicting
  • Backward compatibility requirements undefined
  • Migration impact not assessed
  • Client communication strategy missing

Skill Version: 1.0.0