12 Commits

Author SHA1 Message Date
Jean-Marc Strauven
6c24d290f4 Merge pull request #7 from Grazulex/feat/apiroute-v2
feat!: upgrade to laravel-apiroute v2.0
2026-01-02 17:50:00 +01:00
Jean-Marc Strauven
396207d6b0 Merge branch 'main' into feat/apiroute-v2 2026-01-02 17:49:51 +01:00
Jean-Marc Strauven
7a35de80d0 feat!: upgrade to laravel-apiroute v2.0 with config-based versioning
- Update composer.json to require grazulex/laravel-apiroute ^2.0
- Add versions config to config/apiroute.php
- Create routes/api/v1.php with version 1 routes
- Update routes/api.php to remove imperative version declarations
- Update README.md with new v2.x documentation

BREAKING CHANGE: API versions are now declared in config/apiroute.php
instead of routes/api.php
2026-01-02 17:47:38 +01:00
Jean-Marc Strauven
9f0d41d827 Merge pull request #5 from Grazulex/fix/php-requirement-rate-limiting
fix: align PHP requirement and implement rate limiting
2025-12-30 15:35:29 +01:00
Jean-Marc Strauven
562448f576 Merge branch 'main' into fix/php-requirement-rate-limiting 2025-12-30 15:35:22 +01:00
Jean-Marc Strauven
cb911a3c04 Merge pull request #4 from Trpsky/feature
Fix : laravel-apiroute version mismatch and upgrade Pest to v4 for Laravel 12 compatibility
2025-12-30 15:34:33 +01:00
Jean-Marc Strauven
06ee9a5016 fix: align PHP requirement and implement rate limiting
- Update composer.json to require PHP ^8.3 (required by grazulex/laravel-apiroute ^1.2)
- Add rate limiting to routes using laravel-apiroute's rateLimit() and Laravel's throttle middleware
  - Public routes (login/register): throttle:auth (5/min for brute force protection)
  - Protected routes: throttle:authenticated (120/min)
  - Global version rate limit: 60 req/min via ->rateLimit(60)
- Remove unused import in routes/web.php (fixes Pint style issue)
- Update composer.lock with synchronized dependencies
2025-12-30 15:33:20 +01:00
ELMEHDI ACHAHED
0113b0112b Fix : dependency mismatch and upgrade Pest for Laravel 12 support
This commit resolves the version mismatch for 'grazulex/laravel-apiroute' by regenerating the lock file. Additionally, it upgrades 'pestphp/pest' and 'pestphp/pest-plugin-laravel' to v4 to ensure compatibility with Laravel 12 and PHPUnit 12, fixing dependency conflicts.
The lock file was out of sync with composer.json, causing installation failures. Upgrading to Pest v4 is necessary as Pest v3 conflicts with PHPUnit 12, which is required by Laravel 12.
2025-12-30 11:05:45 +01:00
Jean-Marc Strauven
ae8d4bd432 Merge pull request #1 from Grazulex/chore/update-laravel-apiroute-1.2.0
chore(deps): update laravel-apiroute to ^1.2
2025-12-28 19:16:16 +01:00
Jean-Marc Strauven
c9fbf64472 chore(deps): update laravel-apiroute to ^1.2 2025-12-28 19:15:17 +01:00
Jean-Marc Strauven
d93b82b1eb chore(release): 1.1.0 2025-12-25 07:33:38 +01:00
Jean-Marc Strauven
02c55f765f chore(deps): update laravel-apiroute to ^1.0
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 07:33:08 +01:00
8 changed files with 577 additions and 554 deletions

View File

@@ -2,6 +2,11 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [1.1.0](https://github.com/Grazulex/laravel-api-kit/releases/tag/v1.1.0) (2025-12-25)
### Chores
- **deps:** update laravel-apiroute to ^1.0 ([02c55f7](https://github.com/Grazulex/laravel-api-kit/commit/02c55f765f103852258398d7d0d0790146a33f10))
## [1.0.0](https://github.com/Grazulex/laravel-api-kit/releases/tag/v1.0.0) (2025-12-25) ## [1.0.0](https://github.com/Grazulex/laravel-api-kit/releases/tag/v1.0.0) (2025-12-25)
### Features ### Features

View File

@@ -230,7 +230,9 @@ laravel-api-kit/
│ ├── sanctum.php # Token auth config │ ├── sanctum.php # Token auth config
│ └── scramble.php # API docs config │ └── scramble.php # API docs config
├── routes/ ├── routes/
── api.php # API routes with versioning ── api.php # API routes entry point
│ └── api/
│ └── v1.php # Version 1 routes
├── tests/ ├── tests/
│ └── Feature/Api/V1/ │ └── Feature/Api/V1/
│ └── AuthTest.php # Authentication tests │ └── AuthTest.php # Authentication tests
@@ -241,7 +243,7 @@ laravel-api-kit/
## API Versioning ## API Versioning
This kit uses [grazulex/laravel-apiroute](https://github.com/Grazulex/laravel-apiroute) for API versioning with support for: This kit uses [grazulex/laravel-apiroute](https://github.com/Grazulex/laravel-apiroute) v2.x for API versioning with support for:
- **URI Path** (default): `/api/v1/users`, `/api/v2/users` - **URI Path** (default): `/api/v1/users`, `/api/v2/users`
- **Header**: `X-API-Version: 2` - **Header**: `X-API-Version: 2`
@@ -252,22 +254,34 @@ This kit uses [grazulex/laravel-apiroute](https://github.com/Grazulex/laravel-ap
1. Create controllers in `app/Http/Controllers/Api/V2/` 1. Create controllers in `app/Http/Controllers/Api/V2/`
2. Create requests in `app/Http/Requests/Api/V2/` 2. Create requests in `app/Http/Requests/Api/V2/`
3. Update `routes/api.php`: 3. Create route file `routes/api/v2.php`:
```php ```php
use Grazulex\ApiRoute\Facades\ApiRoute; <?php
// Version 2 - New current version use App\Http\Controllers\Api\V2\AuthController;
ApiRoute::version('v2', function () { use Illuminate\Support\Facades\Route;
Route::post('register', [V2\AuthController::class, 'register']);
// ... more routes
})->current();
// Version 1 - Mark as deprecated Route::post('register', [AuthController::class, 'register']);
ApiRoute::version('v1', function () { // ... more routes
Route::post('register', [V1\AuthController::class, 'register']); ```
// ... existing routes
})->deprecated('2025-06-01')->sunset('2025-12-01'); 4. Update `config/apiroute.php`:
```php
'versions' => [
'v1' => [
'routes' => base_path('routes/api/v1.php'),
'status' => 'deprecated',
'deprecated_at' => '2025-06-01',
'sunset_at' => '2025-12-01',
'successor' => 'v2',
],
'v2' => [
'routes' => base_path('routes/api/v2.php'),
'status' => 'active',
],
],
``` ```
### Deprecation Headers ### Deprecation Headers
@@ -275,8 +289,8 @@ ApiRoute::version('v1', function () {
When accessing deprecated versions, responses include RFC-compliant headers: When accessing deprecated versions, responses include RFC-compliant headers:
```http ```http
Deprecation: @1717200000 Deprecation: Sun, 01 Jun 2025 00:00:00 GMT
Sunset: Sun, 01 Dec 2025 00:00:00 GMT Sunset: Mon, 01 Dec 2025 00:00:00 GMT
Link: </api/v2>; rel="successor-version" Link: </api/v2>; rel="successor-version"
``` ```
@@ -574,14 +588,11 @@ class PostResource extends JsonResource
4. **Add Routes:** 4. **Add Routes:**
```php ```php
// routes/api.php // routes/api/v1.php
ApiRoute::version('v1', function () { Route::middleware('auth:sanctum')->group(function () {
// ... existing routes // ... existing routes
Route::apiResource('posts', PostController::class);
Route::middleware('auth:sanctum')->group(function () { });
Route::apiResource('posts', PostController::class);
});
})->current();
``` ```
5. **Create Tests:** 5. **Create Tests:**

View File

@@ -6,9 +6,9 @@
"keywords": ["laravel", "api", "rest", "starter-kit", "sanctum"], "keywords": ["laravel", "api", "rest", "starter-kit", "sanctum"],
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^8.2", "php": "^8.3",
"dedoc/scramble": "^0.12", "dedoc/scramble": "^0.12",
"grazulex/laravel-apiroute": "^0.0", "grazulex/laravel-apiroute": "^2.0",
"laravel/framework": "^12.0", "laravel/framework": "^12.0",
"laravel/sanctum": "^4.0", "laravel/sanctum": "^4.0",
"laravel/tinker": "^2.10.1", "laravel/tinker": "^2.10.1",
@@ -21,8 +21,8 @@
"laravel/pint": "^1.24", "laravel/pint": "^1.24",
"mockery/mockery": "^1.6", "mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.6", "nunomaduro/collision": "^8.6",
"pestphp/pest": "^3.0", "pestphp/pest": "^4.0",
"pestphp/pest-plugin-laravel": "^3.0" "pestphp/pest-plugin-laravel": "^4.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

989
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,28 @@
declare(strict_types=1); declare(strict_types=1);
return [ return [
/*
|--------------------------------------------------------------------------
| API Versions
|--------------------------------------------------------------------------
|
| Define your API versions here. Each version has its own route file,
| middleware, and lifecycle status.
|
*/
'versions' => [
'v1' => [
'routes' => base_path('routes/api/v1.php'),
'middleware' => [],
'status' => 'active',
'deprecated_at' => null,
'sunset_at' => null,
'successor' => null,
'documentation' => null,
'rate_limit' => null,
],
],
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Detection Strategy | Detection Strategy

View File

@@ -1,15 +1,14 @@
<?php <?php
use App\Http\Controllers\Api\V1\AuthController;
use Grazulex\ApiRoute\Facades\ApiRoute;
use Illuminate\Support\Facades\Route;
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| API Routes | API Routes
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| API routes are versioned using grazulex/laravel-apiroute. | API routes are versioned using grazulex/laravel-apiroute v2.x.
| Versions are defined in config/apiroute.php and route files are
| located in routes/api/{version}.php
|
| Supports URI path, header, query, and Accept header detection. | Supports URI path, header, query, and Accept header detection.
| See config/apiroute.php for configuration options. | See config/apiroute.php for configuration options.
| |
@@ -17,13 +16,17 @@ use Illuminate\Support\Facades\Route;
// Version 1 - Current stable version // Version 1 - Current stable version
ApiRoute::version('v1', function () { ApiRoute::version('v1', function () {
// Public routes // Public routes with auth rate limiter (5/min - brute force protection)
Route::post('register', [AuthController::class, 'register'])->name('api.v1.register'); Route::middleware('throttle:auth')->group(function () {
Route::post('login', [AuthController::class, 'login'])->name('api.v1.login'); Route::post('register', [AuthController::class, 'register'])->name('api.v1.register');
Route::post('login', [AuthController::class, 'login'])->name('api.v1.login');
});
// Protected routes // Protected routes with authenticated rate limiter (120/min)
Route::middleware('auth:sanctum')->group(function () { Route::middleware(['auth:sanctum', 'throttle:authenticated'])->group(function () {
Route::post('logout', [AuthController::class, 'logout'])->name('api.v1.logout'); Route::post('logout', [AuthController::class, 'logout'])->name('api.v1.logout');
Route::get('me', [AuthController::class, 'me'])->name('api.v1.me'); Route::get('me', [AuthController::class, 'me'])->name('api.v1.me');
}); });
})->current(); })
->current()
->rateLimit(60); // Global rate limit: 60 requests/minute for v1

23
routes/api/v1.php Normal file
View File

@@ -0,0 +1,23 @@
<?php
use App\Http\Controllers\Api\V1\AuthController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API V1 Routes
|--------------------------------------------------------------------------
|
| Routes for API version 1.
|
*/
// Public routes
Route::post('register', [AuthController::class, 'register'])->name('api.v1.register');
Route::post('login', [AuthController::class, 'login'])->name('api.v1.login');
// Protected routes
Route::middleware('auth:sanctum')->group(function () {
Route::post('logout', [AuthController::class, 'logout'])->name('api.v1.logout');
Route::get('me', [AuthController::class, 'me'])->name('api.v1.me');
});

View File

@@ -1,6 +1,4 @@
<?php <?php
use Illuminate\Support\Facades\Route;
// Web routes disabled - API only application // Web routes disabled - API only application
// Scramble documentation available at /docs/api // Scramble documentation available at /docs/api