ForgeBase SDK for Dart/Flutter

A powerful and flexible Dart SDK for interacting with ForgeBase databases. This SDK provides a fluent interface for building complex queries, performing CRUD operations, and working with advanced database features like window functions, CTEs, and aggregates.

Features

  • 🚀 Fluent Query Builder API: Build type-safe database queries with an intuitive builder pattern
  • 🔒 Type Safety: Full TypeScript-like generic support for your data models
  • 🔄 CRUD Operations: Simple methods for Create, Read, Update, and Delete operations
  • 📊 Advanced Query Features:
    • Complex filtering with AND/OR conditions
    • Window functions and analytics
    • Common Table Expressions (CTEs)
    • Aggregations and grouping
    • Subqueries and EXISTS clauses
    • Pagination and sorting
    • Data transformations and computations
  • 🔄 Result Transformations:
    • Compute derived fields
    • Pivot data for cross-tabulation
    • Group and aggregate results
  • 🔐 Authentication Support: Easily integrate with authentication systems
  • 🧠 Query Validation: Validate queries before execution
  • 📦 Caching Support: Cache query results for better performance
  • Performance: Optimized HTTP client using Dio
  • 🔍 Error Handling: Detailed error messages and proper error typing

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  forgebase_sdk: ^0.0.2

Quick Start

// Initialize the SDK
final sdk = DatabaseSDK('https://your-forgebase-api.com');

// Simple query
final users = await sdk
    .table<Map<String, dynamic>>('users')
    .where('status', 'active')
    .limit(10)
    .execute();

// Complex query with joins and aggregates
final orderStats = await sdk
    .table<Map<String, dynamic>>('orders')
    .whereExists((subquery) =>
      subquery.table('order_items')
        .where('order_items.order_id', '=', 'orders.id')
        .where('quantity', '>', 10)
    )
    .groupBy(['status'])
    .having('total_amount', WhereOperator.greaterThan, 1000)
    .sum('amount', alias: 'total_amount')
    .execute();

Advanced Features

Window Functions

final rankedSalaries = await sdk
    .table<Map<String, dynamic>>('employees')
    .windowAdvanced(
      WindowFunctionType.rowNumber,
      'salary_rank',
      over: WindowOver(
        partitionBy: ['department'],
        orderBy: [OrderByClause(field: 'salary', direction: SortDirection.desc)]
      ),
    )
    .execute();

Common Table Expressions (CTEs)

final hierarchicalData = await sdk
    .table<Map<String, dynamic>>('employees')
    .withRecursive(
      'employee_hierarchy',
      initialQuery,
      recursiveQuery,
      columns: ['id', 'manager_id', 'level'],
    )
    .execute();

Aggregations

final stats = await sdk
    .table<Map<String, dynamic>>('sales')
    .groupBy(['region'])
    .sum('amount', alias: 'total_sales')
    .avg('amount', alias: 'average_sale')
    .count('id', alias: 'num_transactions')
    .execute();

Error Handling

The SDK provides detailed error information through the ForgeBaseException class:

try {
  final result = await sdk.table('users').execute();
} on ForgeBaseException catch (e) {
  print('Error: ${e.message}');
  print('Code: ${e.code}');
  print('Status: ${e.statusCode}');
}

API Reference

DatabaseSDK

The main entry point for interacting with your ForgeBase database.

// Basic initialization
final sdk = DatabaseSDK(
  'https://api.example.com',
  interceptors: [], // Optional Dio interceptors
  dioOptions: BaseOptions(), // Optional Dio configuration
);

// With custom Dio instance (e.g., for authentication)
final customDio = Dio();
customDio.interceptors.add(AuthInterceptor());
final sdk = DatabaseSDK.withDio(
  'https://api.example.com',
  dio: customDio,
);

Transformations

Transform query results with computed fields, pivoting, and grouping:

// Compute derived fields
final results = await sdk
    .table<Map<String, dynamic>>('orders')
    .compute({
      'discountedTotal': (row) => row['total'] * 0.9,
      'fullName': (row) => '${row['firstName']} ${row['lastName']}',
    })
    .execute();

// Pivot data
final pivotedData = await sdk
    .table<Map<String, dynamic>>('sales')
    .pivot(
      'quarter',
      ['Q1', 'Q2', 'Q3', 'Q4'],
      AggregateOptions(
        type: AggregateType.sum,
        field: 'amount',
      ),
    )
    .execute();

Caching and Validation

// With caching
final cachedResults = await sdk.getRecords<Map<String, dynamic>>(
  tableName: 'products',
  params: QueryParams(
    filter: {'category': 'electronics'},
  ),
  cache: CacheConfig(
    ttl: 300, // 5 minutes
    key: 'electronics-products',
    tags: ['products', 'electronics'],
  ),
);

// With validation
final validatedResults = await sdk.getRecords<Map<String, dynamic>>(
  tableName: 'users',
  params: QueryParams(
    select: ['id', 'name', 'email'],
  ),
  validation: QueryValidation(
    rules: ValidationRules(
      maxLimit: 100,
      requiredFields: ['id'],
      disallowedFields: ['password'],
    ),
    suggestions: true,
  ),
);

QueryBuilder

Methods for building database queries:

  • where(field, operator, value): Add a where clause
  • orWhere((query) => ...): Add an OR where clause
  • whereExists((subquery) => ...): Add a where exists clause
  • select(fields): Select specific fields (accepts both list and variable arguments)
  • groupBy(fields): Group results by fields (accepts both list and variable arguments)
  • orderBy(field, direction, nulls): Sort results
  • limit(value): Limit number of results
  • offset(value): Skip number of results
  • compute(computations): Add computed fields
  • pivot(column, values, aggregate): Pivot data for cross-tabulation
  • explain(options): Get query execution plan
  • And many more...

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

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

Libraries

forgebase_sdk
A Dart/Flutter client SDK for ForgeBase