api_kit 0.0.4 copy "api_kit: ^0.0.4" to clipboard
api_kit: ^0.0.4 copied to clipboard

Production-ready REST API framework with comprehensive JWT authentication system, custom validators, annotation-based routing, token blacklisting, etc.

example/example.dart

import 'dart:io';
import 'package:api_kit/api_kit.dart';
import 'package:logger_rs/logger_rs.dart';

/// Example demonstration of api_kit framework with a complete REST API server.
///
/// This example showcases the main features of api_kit:
/// - Annotation-based routing with controllers
/// - Clean server configuration
/// - Built-in error handling with Result pattern
/// - Graceful shutdown handling
/// - Production-ready development configuration
///
/// ## Running the Example
///
/// 1. Run with: `dart run example/example.dart`
/// 2. Test endpoints:
///    - GET http://localhost:8080/health (health check)
///    - GET http://localhost:8080/api/v1/users (list users)
///    - POST http://localhost:8080/api/v1/users (create user)
///    - GET http://localhost:8080/api/v1/users/1 (get specific user)
///    - PUT http://localhost:8080/api/v1/users/1 (update user)
///    - DELETE http://localhost:8080/api/v1/users/1 (delete user)
///
/// ## Server Configuration
///
/// Uses `ServerConfig.development()` which includes:
/// - Permissive CORS for local development
/// - Verbose request logging
/// - Development-friendly error messages
///
/// For production, use `ServerConfig.production()` instead.
void main() async {
  // Create API server with development configuration
  final server = ApiServer(
    config: ServerConfig.development(), // Use development for example
  );

  // Start the server with controller list (simple_rest style!)
  final result = await server.start(
    host: 'localhost',
    port: 8080,
    controllerList: [
      UserController(), // Just add controllers to the list!
      // ProductController(), // Add more controllers here
      // OrderController(),
    ],
  );

  result.when(
    ok: (httpServer) {
      Log.i('Example server running on http://localhost:8080');
      Log.i('Try: curl http://localhost:8080/health');
      Log.i('Try: curl http://localhost:8080/api/v1/users');
      Log.i(
        'Try: curl -X POST http://localhost:8080/api/v1/users -d \'{"name":"John"}\'',
      );

      // Handle graceful shutdown
      ProcessSignal.sigint.watch().listen((_) async {
        Log.i('Shutting down server...');
        await server.stop(httpServer);
        exit(0);
      });
    },
    err: (apiErr) {
      Log.e(
        'Failed to start server',
        error: apiErr.exception,
        stackTrace: apiErr.stackTrace,
      );
      exit(1);
    },
  );
}

/// Example user controller demonstrating annotation-based REST API routing.
///
/// This controller showcases the main features of api_kit controllers:
/// - Automatic route registration with `@Controller` annotation
/// - HTTP method annotations (`@GET`, `@POST`, `@PUT`, `@DELETE`)
/// - Path parameter extraction with angle brackets (`<id>`)
/// - Built-in request logging and error handling
/// - Standardized JSON response format with `ApiResponse`
///
/// ## Supported Endpoints
///
/// - `GET /api/v1/users` - List all users
/// - `GET /api/v1/users/<id>` - Get user by ID
/// - `POST /api/v1/users` - Create new user
/// - `PUT /api/v1/users/<id>` - Update existing user
/// - `DELETE /api/v1/users/<id>` - Delete user by ID
///
/// ## Implementation Notes
///
/// - Uses in-memory storage for demonstration (replace with database in production)
/// - Includes proper HTTP status codes (200, 201, 404, 400, 500)
/// - Validates required parameters and request bodies
/// - Provides consistent error handling and logging
/// - Returns standardized JSON responses using `ApiResponse` pattern
@Controller('/api/v1/users')
class UserController extends BaseController {
  /// In-memory user storage for demonstration purposes.
  /// In production, replace with proper database integration.
  final List<Map<String, dynamic>> _users = [
    {'id': '1', 'name': 'Alice', 'email': 'alice@example.com'},
    {'id': '2', 'name': 'Bob', 'email': 'bob@example.com'},
  ];

  // No need to override router - it's built automatically from annotations!

  /// Retrieves a list of all users.
  ///
  /// Returns a JSON array containing all users with their basic information.
  /// This endpoint demonstrates the simplest GET request handling.
  ///
  /// **HTTP Method:** GET
  /// **Endpoint:** `/api/v1/users`
  /// **Response:** 200 OK with user list
  ///
  /// Example response:
  /// ```json
  /// {
  ///   "success": true,
  ///   "message": "Users retrieved successfully",
  ///   "data": [
  ///     {"id": "1", "name": "Alice", "email": "alice@example.com"},
  ///     {"id": "2", "name": "Bob", "email": "bob@example.com"}
  ///   ]
  /// }
  /// ```
  @GET('/')
  Future<Response> getUsers(Request request) async {
    logRequest(request, 'Getting all users');

    final response = ApiResponse.success(
      _users,
      'Users retrieved successfully',
    );
    return jsonResponse(response.toJson());
  }

  /// Retrieves a specific user by their ID.
  ///
  /// Demonstrates path parameter extraction using angle brackets syntax (`<id>`).
  /// The framework automatically extracts the ID from the URL path and makes it
  /// available through `getRequiredParam()`.
  ///
  /// **HTTP Method:** GET
  /// **Endpoint:** `/api/v1/users/<id>`
  /// **Parameters:**
  /// - `id` (path): User ID to retrieve
  ///
  /// **Responses:**
  /// - 200 OK: User found and returned
  /// - 404 Not Found: User with specified ID doesn't exist
  ///
  /// Example successful response:
  /// ```json
  /// {
  ///   "success": true,
  ///   "data": {"id": "1", "name": "Alice", "email": "alice@example.com"}
  /// }
  /// ```
  ///
  /// Example error response:
  /// ```json
  /// {
  ///   "success": false,
  ///   "message": "User not found"
  /// }
  /// ```
  @GET('/<id>')
  Future<Response> getUser(Request request) async {
    final id = getRequiredParam(request, 'id');
    logRequest(request, 'Getting user $id');

    final user = _users.firstWhere((u) => u['id'] == id, orElse: () => {});

    final response = user.isEmpty
        ? ApiResponse.notFound('User not found')
        : ApiResponse.success(user);

    final statusCode = user.isEmpty ? 404 : 200;
    return jsonResponse(response.toJson(), statusCode: statusCode);
  }

  /// Creates a new user from the provided JSON data.
  ///
  /// Demonstrates POST request handling with request body validation.
  /// Shows proper HTTP status code usage (201 Created for successful creation).
  ///
  /// **HTTP Method:** POST
  /// **Endpoint:** `/api/v1/users`
  /// **Request Body:** JSON object with user data
  ///
  /// **Responses:**
  /// - 201 Created: User successfully created
  /// - 400 Bad Request: Missing or invalid request body
  ///
  /// Expected request body format:
  /// ```json
  /// {
  ///   "name": "John Doe",
  ///   "email": "john@example.com"
  /// }
  /// ```
  ///
  /// Example successful response:
  /// ```json
  /// {
  ///   "success": true,
  ///   "message": "User created successfully",
  ///   "data": {
  ///     "id": "3",
  ///     "name": "New User",
  ///     "email": "new@example.com"
  ///   }
  /// }
  /// ```
  ///
  /// Note: This example uses simplified user creation for demonstration.
  /// In production, implement proper JSON parsing, validation, and database storage.
  @POST('/')
  Future<Response> createUser(Request request) async {
    logRequest(request, 'Creating new user');

    final body = await request.readAsString();
    if (body.isEmpty) {
      final response = ApiResponse.badRequest('Request body is required');
      return jsonResponse(response.toJson(), statusCode: 400);
    }

    // In a real app, you would validate and parse the JSON here
    final newUser = {
      'id': '${_users.length + 1}',
      'name': 'New User',
      'email': 'new@example.com',
    };

    _users.add(newUser);

    final response = ApiResponse.success(newUser, 'User created successfully');
    return jsonResponse(response.toJson(), statusCode: 201);
  }

  /// Updates an existing user with new data.
  ///
  /// Combines path parameter extraction with request body processing.
  /// Demonstrates proper error handling with try-catch blocks and
  /// different HTTP status codes for various scenarios.
  ///
  /// **HTTP Method:** PUT
  /// **Endpoint:** `/api/v1/users/<id>`
  /// **Parameters:**
  /// - `id` (path): User ID to update
  ///
  /// **Request Body:** JSON object with updated user data
  ///
  /// **Responses:**
  /// - 200 OK: User successfully updated
  /// - 404 Not Found: User with specified ID doesn't exist
  /// - 500 Internal Server Error: Update operation failed
  ///
  /// Expected request body format:
  /// ```json
  /// {
  ///   "name": "Updated Name",
  ///   "email": "updated@example.com"
  /// }
  /// ```
  ///
  /// Example successful response:
  /// ```json
  /// {
  ///   "success": true,
  ///   "message": "User updated successfully",
  ///   "data": {
  ///     "id": "1",
  ///     "name": "Updated User",
  ///     "email": "alice@example.com"
  ///   }
  /// }
  /// ```
  ///
  /// Note: This example demonstrates basic update flow.
  /// In production, implement proper JSON parsing, field validation,
  /// and database transactions with rollback capability.
  @PUT('/<id>')
  Future<Response> updateUser(Request request) async {
    final id = getRequiredParam(request, 'id');
    logRequest(request, 'Updating user $id');

    final userIndex = _users.indexWhere((u) => u['id'] == id);
    if (userIndex == -1) {
      final response = ApiResponse.notFound('User not found');
      return jsonResponse(response.toJson(), statusCode: 404);
    }

    try {
      await request.readAsString();
      // In a real app, you would parse and validate the JSON here
      _users[userIndex]['name'] = 'Updated User';

      final response = ApiResponse.success(
        _users[userIndex],
        'User updated successfully',
      );
      return jsonResponse(response.toJson());
    } catch (e) {
      Log.e('Error updating user', error: e);
      final response = ApiResponse.error('Failed to update user');
      return jsonResponse(response.toJson(), statusCode: 500);
    }
  }

  /// Deletes a user by their ID.
  ///
  /// Demonstrates DELETE operation with proper resource validation.
  /// Shows how to handle deletion scenarios and return appropriate
  /// responses for both successful and failed operations.
  ///
  /// **HTTP Method:** DELETE
  /// **Endpoint:** `/api/v1/users/<id>`
  /// **Parameters:**
  /// - `id` (path): User ID to delete
  ///
  /// **Responses:**
  /// - 200 OK: User successfully deleted
  /// - 404 Not Found: User with specified ID doesn't exist
  ///
  /// Example successful response:
  /// ```json
  /// {
  ///   "success": true,
  ///   "message": "User deleted successfully",
  ///   "data": null
  /// }
  /// ```
  ///
  /// Example error response:
  /// ```json
  /// {
  ///   "success": false,
  ///   "message": "User not found"
  /// }
  /// ```
  ///
  /// Note: This example performs immediate deletion from memory.
  /// In production, consider implementing:
  /// - Soft deletion (marking as deleted rather than removing)
  /// - Transaction-based deletion for data integrity
  /// - Cascade deletion handling for related records
  /// - Audit logging for deletion tracking
  @DELETE('/<id>')
  Future<Response> deleteUser(Request request) async {
    final id = getRequiredParam(request, 'id');
    logRequest(request, 'Deleting user $id');

    final userIndex = _users.indexWhere((u) => u['id'] == id);
    if (userIndex == -1) {
      final response = ApiResponse.notFound('User not found');
      return jsonResponse(response.toJson(), statusCode: 404);
    }

    _users.removeAt(userIndex);

    final response = ApiResponse.success(null, 'User deleted successfully');
    return jsonResponse(response.toJson());
  }
}
1
likes
0
points
86
downloads

Publisher

verified publisherjhonacode.com

Weekly Downloads

Production-ready REST API framework with comprehensive JWT authentication system, custom validators, annotation-based routing, token blacklisting, etc.

Repository (GitHub)
View/report issues

Topics

#api #server #http #jwt #middleware

Documentation

Documentation

License

unknown (license)

Dependencies

convert, http, logger_rs, result_controller, shelf, shelf_router

More

Packages that depend on api_kit