๐Ÿš€ Glider API

A FastAPI-inspired Dart backend server package for building APIs with ease

Dart License Version

Glider API is a powerful, lightweight, and developer-friendly backend framework for Dart that brings the elegance and simplicity of FastAPI to the Dart ecosystem. Build robust REST APIs with minimal boilerplate code, automatic documentation generation, and built-in validation.

๐Ÿ“ Example API

Here's a complete working example of a REST API built with Glider API:

import 'package:glider_api/glider_api.dart';

Future<void> main() async {
  final app = ApiClient();

  app.enableDevelopmentMode(enableDocs: true);

  app.use(GliderMiddleware.cors());
  app.use(GliderMiddleware.jsonParser());
  app.use(GliderMiddleware.errorHandler(includeStackTrace: true));

  app.get('/', () => {'message': 'Hello from glider_api'});

  var usersList = [];

  app.get('/users', () => GliderResponse.ok(usersList));

  app.post('/users', (GliderRequest req) async {
    final name = await req.validateField('name', Validators.string(minLength: 2));
    final email = await req.validateField('email', Validators.email);
    usersList.add({'id': usersList.length + 1, 'name': name, 'email': email});
    return GliderResponse.ok({'name': name, 'email': email});
  });
  
  app.patch('/users/<id>', (GliderRequest req) async {
    final id = req.param('id');
    final name = await req.validateField('name', Validators.string(minLength: 2));
    final email = await req.validateField('email', Validators.email);
    final user = usersList.firstWhere((user) => user['id'] == int.parse(id!));
    user['name'] = name;
    user['email'] = email;
    return GliderResponse.ok(user);
  });

  app.delete('/users/<id>', (GliderRequest req) async {
    final id = req.param('id');
    usersList.removeWhere((user) => user['id'] == int.parse(id!));
    return GliderResponse.ok({"message": "User deleted", "id": id, "users": usersList});
  });

  await app.listen(port: 8080);
}

Try it out:

# Run the example
dart run example/simple_api.dart

# Test the API
curl http://localhost:8080/
curl http://localhost:8080/users
curl -X POST http://localhost:8080/users -H "Content-Type: application/json" -d '{"name":"John Doe","email":"john@example.com"}'

โœจ Features

๐ŸŽฏ Core Features

  • FastAPI-inspired Syntax: Familiar and intuitive API design patterns
  • Automatic Documentation: OpenAPI/Swagger docs generation out of the box
  • Built-in Validation: Comprehensive request validation with custom validators
  • Middleware Support: Flexible middleware system for cross-cutting concerns
  • Type Safety: Full Dart type safety with generic route handlers
  • Development Tools: Rich development experience with logging and debugging

๐Ÿ”ง Development Features

  • Hot Reload: Development server with automatic reloading
  • Request Logging: Detailed request/response logging for debugging
  • Error Handling: Comprehensive error handling with stack traces
  • CORS Support: Built-in CORS middleware for cross-origin requests
  • JSON Parsing: Automatic JSON request body parsing

๐Ÿ“š Documentation & API

  • Auto-generated Docs: Interactive API documentation at /docs
  • OpenAPI Spec: Standard OpenAPI 3.0 specification generation
  • ReDoc Support: Beautiful documentation with ReDoc
  • Schema Learning: Automatic schema inference from request/response data

๐Ÿ›ก๏ธ Security & Validation

  • Input Validation: Built-in validators for strings, emails, numbers, etc.
  • Custom Validators: Create your own validation rules
  • Error Responses: Standardized error response format
  • Request Sanitization: Automatic request data sanitization

๐Ÿš€ Quick Start

Installation

Add glider_api to your pubspec.yaml:

dependencies:
  glider_api: ^0.0.1

Basic Example

import 'package:glider_api/glider_api.dart';

Future<void> main() async {
  final app = ApiClient();

  // Enable development mode with docs
  app.enableDevelopmentMode(enableDocs: true);

  // Add global middleware
  app.use(GliderMiddleware.cors());
  app.use(GliderMiddleware.jsonParser());
  app.use(GliderMiddleware.errorHandler(includeStackTrace: true));

  // Define routes
  app.get('/', () => {'message': 'Hello from glider_api!'});

  app.get('/users', () => GliderResponse.ok([
    {'id': 1, 'name': 'John Doe', 'email': 'john@example.com'},
    {'id': 2, 'name': 'Jane Smith', 'email': 'jane@example.com'},
  ]));

  app.post('/users', (GliderRequest req) async {
    final name = await req.validateField('name', Validators.string(minLength: 2));
    final email = await req.validateField('email', Validators.email);
    
    return GliderResponse.ok({
      'id': DateTime.now().millisecondsSinceEpoch,
      'name': name,
      'email': email,
    });
  });

  // Start the server
  await app.listen(port: 8080);
}

๐Ÿ—„๏ธ PostgreSQL Integration Demo

Setting up PostgreSQL with Glider API

This section demonstrates how to integrate PostgreSQL with your Glider API application.

1. Install PostgreSQL Dependencies

# Install PostgreSQL client for Dart
dart pub add postgres

2. Database Configuration

import 'package:postgres/postgres.dart';

class DatabaseConfig {
  static const String host = 'localhost';
  static const int port = 5432;
  static const String database = 'glider_api_db';
  static const String username = 'postgres';
  static const String password = 'your_password';
  
  static PostgreSQLConnection get connection => PostgreSQLConnection(
    host,
    port,
    database,
    username: username,
    password: password,
  );
}

3. Database Service

class UserService {
  final PostgreSQLConnection _db;
  
  UserService(this._db);
  
  Future<void> initialize() async {
    await _db.open();
    
    // Create users table
    await _db.execute('''
      CREATE TABLE IF NOT EXISTS users (
        id SERIAL PRIMARY KEY,
        name VARCHAR(255) NOT NULL,
        email VARCHAR(255) UNIQUE NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
      )
    ''');
  }
  
  Future<List<Map<String, dynamic>>> getAllUsers() async {
    final results = await _db.query('SELECT * FROM users ORDER BY created_at DESC');
    return results.map((row) => {
      'id': row[0],
      'name': row[1],
      'email': row[2],
      'created_at': row[3],
    }).toList();
  }
  
  Future<Map<String, dynamic>?> getUserById(int id) async {
    final results = await _db.query(
      'SELECT * FROM users WHERE id = @id',
      substitutionValues: {'id': id},
    );
    
    if (results.isEmpty) return null;
    
    final row = results.first;
    return {
      'id': row[0],
      'name': row[1],
      'email': row[2],
      'created_at': row[3],
    };
  }
  
  Future<Map<String, dynamic>> createUser(String name, String email) async {
    final results = await _db.query(
      'INSERT INTO users (name, email) VALUES (@name, @email) RETURNING *',
      substitutionValues: {'name': name, 'email': email},
    );
    
    final row = results.first;
    return {
      'id': row[0],
      'name': row[1],
      'email': row[2],
      'created_at': row[3],
    };
  }
  
  Future<Map<String, dynamic>?> updateUser(int id, String name, String email) async {
    final results = await _db.query(
      'UPDATE users SET name = @name, email = @email WHERE id = @id RETURNING *',
      substitutionValues: {'id': id, 'name': name, 'email': email},
    );
    
    if (results.isEmpty) return null;
    
    final row = results.first;
    return {
      'id': row[0],
      'name': row[1],
      'email': row[2],
      'created_at': row[3],
    };
  }
  
  Future<bool> deleteUser(int id) async {
    final results = await _db.query(
      'DELETE FROM users WHERE id = @id',
      substitutionValues: {'id': id},
    );
    return results.isNotEmpty;
  }
}

4. API with PostgreSQL Integration

import 'package:glider_api/glider_api.dart';
import 'package:postgres/postgres.dart';

Future<void> main() async {
  final app = ApiClient();
  
  // Initialize database
  final db = DatabaseConfig.connection;
  final userService = UserService(db);
  await userService.initialize();
  
  app.enableDevelopmentMode(enableDocs: true);
  app.use(GliderMiddleware.cors());
  app.use(GliderMiddleware.jsonParser());
  app.use(GliderMiddleware.errorHandler(includeStackTrace: true));
  
  // User routes with PostgreSQL
  app.get('/users', () async {
    final users = await userService.getAllUsers();
    return GliderResponse.ok(users);
  });
  
  app.get('/users/<id>', (GliderRequest req) async {
    final id = int.tryParse(req.param('id') ?? '');
    if (id == null) {
      return GliderResponse.badRequest('Invalid user ID');
    }
    
    final user = await userService.getUserById(id);
    if (user == null) {
      return GliderResponse.notFound('User not found');
    }
    
    return GliderResponse.ok(user);
  });
  
  app.post('/users', (GliderRequest req) async {
    final name = await req.validateField('name', Validators.string(minLength: 2));
    final email = await req.validateField('email', Validators.email);
    
    try {
      final user = await userService.createUser(name, email);
      return GliderResponse.created(user);
    } catch (e) {
      if (e.toString().contains('duplicate key')) {
        return GliderResponse.conflict('Email already exists');
      }
      rethrow;
    }
  });
  
  app.patch('/users/<id>', (GliderRequest req) async {
    final id = int.tryParse(req.param('id') ?? '');
    if (id == null) {
      return GliderResponse.badRequest('Invalid user ID');
    }
    
    final name = await req.validateField('name', Validators.string(minLength: 2));
    final email = await req.validateField('email', Validators.email);
    
    final user = await userService.updateUser(id, name, email);
    if (user == null) {
      return GliderResponse.notFound('User not found');
    }
    
    return GliderResponse.ok(user);
  });
  
  app.delete('/users/<id>', (GliderRequest req) async {
    final id = int.tryParse(req.param('id') ?? '');
    if (id == null) {
      return GliderResponse.badRequest('Invalid user ID');
    }
    
    final deleted = await userService.deleteUser(id);
    if (!deleted) {
      return GliderResponse.notFound('User not found');
    }
    
    return GliderResponse.ok({'message': 'User deleted successfully'});
  });
  
  await app.listen(port: 8080);
}

๐Ÿ“‹ API Reference

HTTP Methods

Glider API supports all standard HTTP methods:

app.get('/path', handler);
app.post('/path', handler);
app.put('/path', handler);
app.patch('/path', handler);
app.delete('/path', handler);
app.head('/path', handler);
app.options('/path', handler);

Request Validation

// String validation
final name = await req.validateField('name', Validators.string(minLength: 2, maxLength: 50));

// Email validation
final email = await req.validateField('email', Validators.email);

// Number validation
final age = await req.validateField('age', Validators.number(min: 0, max: 120));

// Custom validation
final customField = await req.validateField('custom', Validators.custom((value) {
  if (value.toString().contains('forbidden')) {
    throw ValidationError('Value contains forbidden content');
  }
  return value;
}));

Response Helpers

// Success responses
GliderResponse.ok(data);
GliderResponse.created(data);
GliderResponse.noContent();

// Error responses
GliderResponse.badRequest('Invalid data');
GliderResponse.unauthorized('Authentication required');
GliderResponse.forbidden('Access denied');
GliderResponse.notFound('Resource not found');
GliderResponse.conflict('Resource conflict');
GliderResponse.internalServerError('Server error');

Middleware

// CORS middleware
app.use(GliderMiddleware.cors());

// JSON parser middleware
app.use(GliderMiddleware.jsonParser());

// Error handler middleware
app.use(GliderMiddleware.errorHandler(includeStackTrace: true));

// Custom middleware
app.use((request, next) async {
  // Pre-processing
  print('Request to: ${request.path}');
  
  final response = await next();
  
  // Post-processing
  print('Response status: ${response.statusCode}');
  
  return response;
});

๐Ÿš€ Deployment Guide

Local Development

# Clone the repository
git clone <your-repo-url>
cd mk_backend

# Install dependencies
dart pub get

# Run the example
dart run example/simple_api.dart

Docker Deployment

1. Create Dockerfile

FROM dart:stable AS build

WORKDIR /app
COPY pubspec.* ./
RUN dart pub get

COPY . .
RUN dart compile exe bin/glider_api.dart -o bin/glider_api

FROM ubuntu:latest

RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY --from=build /app/bin/glider_api /app/bin/glider_api

EXPOSE 8080
CMD ["/app/bin/glider_api"]

2. Build and Run

# Build the Docker image
docker build -t glider-api .

# Run the container
docker run -p 8080:8080 glider-api

Cloud Deployment

Heroku Deployment

  1. Create Procfile:
web: dart run bin/glider_api.dart
  1. Deploy to Heroku:
heroku create your-app-name
git push heroku main

Google Cloud Run

  1. Deploy to Cloud Run:
gcloud run deploy glider-api \
  --source . \
  --platform managed \
  --region us-central1 \
  --allow-unauthenticated

AWS Lambda (with custom runtime)

  1. Create deployment package:
dart compile exe bin/glider_api.dart -o bootstrap
zip -r function.zip bootstrap
  1. Deploy to Lambda:
aws lambda create-function \
  --function-name glider-api \
  --runtime provided.al2 \
  --handler bootstrap \
  --zip-file fileb://function.zip

๐Ÿงช Testing

# Run tests
dart test

# Run tests with coverage
dart test --coverage=coverage
genhtml coverage/lcov.info -o coverage/html

๐Ÿ“– Examples

Check out the example/ directory for complete working examples:

  • Simple API (example/simple_api.dart): Basic CRUD operations
  • Matrimony API (example/matrimonry_api.dart): User management system

๐Ÿค Contributing

We welcome contributions! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ” Open Source Status

โš ๏ธ Important Notice: This repository is currently not open-source yet, but it will be made open-source soon! We're working hard to prepare it for the open-source community.

๐Ÿ‘จโ€๐Ÿ’ป Developer Details

Developed with โค๏ธ by Mirshad Kvr

LinkedIn Instagram


Made with โค๏ธ for the Dart community

โญ Star this repository if you find it helpful!

Libraries

glider_api