iws_http_model 1.0.0 copy "iws_http_model: ^1.0.0" to clipboard
iws_http_model: ^1.0.0 copied to clipboard

unlisted

Library for HTTP requests with the common operations CRUD, pagination and error handling.

Library for HTTP requests with the common CRUD operations, pagination and error handling.

Features #

  • Authentication: JWT token and API key support.
  • HTTP Error Handling: Built-in error handling for HTTP requests.
  • REST Route Builder: Helper methods for building REST API endpoints.
  • Complete CRUD Operations:
    • Get by ID (GET) - Retrieve single records with optional path parameters
    • Paginated Query (GET) - Fetch paginated lists with query parameters
    • Paginated Search (POST) - Advanced search with request body and ordering
    • Create (POST) - Add new records
    • Update (PUT) - Complete record updates
    • Partial Update (PATCH) - Partial record updates
    • Delete (DELETE) - Remove records
  • Flexible Path Management:
    • Custom path support with parameter substitution
    • Dynamic URL generation
    • Support for nested resource paths
  • Advanced Pagination:
    • Built-in pagination metadata handling
    • Configurable page sizes and ordering
    • Support for both GET and POST pagination
  • Type Safety: Full generic type support for model serialization

Getting started #

Initialize the IwsHttp library:

  IwsHttp.setup(
      authority: 'mydomain.com',
      apiKey: 'my_secret_api_key',
      basePath: 'api/',
      secureConnection: true,
      bearerToken: 'my_secret_token');

Usage #

Instantiate IwsHttpModel #

final myModelProvider = IwsHttpModel<MyModelClass>(
    path: 'myModels',
    iwsHttp: IwsHttp(),
    fromJson: MyModelClass.fromJson,
    toJson: MyModelClass.toJson,
    resultAttribute: 'data' // Optional, defaults to 'data'
);

Available Methods #

1. Get by ID

Retrieve a single model by its identifier.

// Basic usage
MyModelClass myModel = await myModelProvider.get(120);

// With custom path and parameters
MyModelClass myModel = await myModelProvider.get(
  120,
  customPath: 'users/{userId}/models',
  pathParams: {'userId': 456},
  queryParameters: {'include': 'relations'},
  auth: true,
  apiKey: true
);

2. Paginated Query (GET)

Retrieve a paginated list of models using GET request.

// Basic usage
PaginatedData<MyModelClass> result = await myModelProvider.fetchPaginated();

// With pagination and query parameters
PaginatedData<MyModelClass> result = await myModelProvider.fetchPaginated(
  page: 2,
  queryParameters: {
    'filter': 'active',
    'orderBy': 'name',
    'orderType': 'asc'
  },
  customPath: 'users/{userId}/models',
  pathParams: {'userId': 456},
  auth: true,
  apiKey: true
);

3. Paginated Search (POST)

Retrieve a paginated list of models using POST request with search criteria.

// Basic usage with search body
PaginatedData<MyModelClass> result = await myModelProvider.fetchPaginatedQuery(
  body: {
    'search': 'search term',
    'filters': {'status': 'active'}
  }
);

// Advanced usage with all parameters
PaginatedData<MyModelClass> result = await myModelProvider.fetchPaginatedQuery(
  page: 1,
  orderBy: 'created_at',
  orderType: OrderType.desc,
  queryParameters: {'include': 'relations'},
  customPath: 'search/models',
  pathParams: {'category': 'electronics'},
  body: {
    'search': 'iPhone',
    'filters': {
      'price_min': 100,
      'price_max': 1000
    }
  },
  auth: true,
  apiKey: true
);

4. Create (POST)

Add a new model.

// Basic usage
MyModelClass newModel = MyModelClass(name: 'New Item');
MyModelClass createdModel = await myModelProvider.add(newModel);

// With custom path and parameters
MyModelClass createdModel = await myModelProvider.add(
  newModel,
  customPath: 'users/{userId}/models',
  pathParams: {'userId': 456}
);

5. Update (PUT)

Update an existing model completely.

// Basic usage
MyModelClass updatedModel = MyModelClass(id: 120, name: 'Updated Item');
MyModelClass result = await myModelProvider.update(updatedModel, 120);

// With custom path and parameters
MyModelClass result = await myModelProvider.update(
  updatedModel,
  120,
  customPath: 'users/{userId}/models',
  pathParams: {'userId': 456}
);

6. Partial Update (PATCH)

Update an existing model partially.

// Basic usage
MyModelClass partialModel = MyModelClass(name: 'Only name updated');
MyModelClass result = await myModelProvider.patchUpdate(partialModel, 120);

// With custom path and parameters
MyModelClass result = await myModelProvider.patchUpdate(
  partialModel,
  120,
  customPath: 'users/{userId}/models',
  pathParams: {'userId': 456}
);

7. Delete

Delete a model by ID.

// Basic usage
await myModelProvider.delete(120);

// With custom path and parameters
await myModelProvider.delete(
  120,
  customPath: 'users/{userId}/models',
  pathParams: {'userId': 456}
);

8. Generate URL

Generate the endpoint URL for debugging or custom requests.

// Basic URL generation
String url = myModelProvider.generateURL();

// With custom path, parameters and ID
String url = myModelProvider.generateURL(
  customPath: 'users/{userId}/models/{modelId}',
  pathParam: {'userId': 456, 'modelId': 120},
  id: '120'
);

Working with Paginated Data #

The fetchPaginated and fetchPaginatedQuery methods return a PaginatedData<T> object:

PaginatedData<MyModelClass> result = await myModelProvider.fetchPaginated();

// Access the data
List<MyModelClass> models = result.data;

// Access pagination metadata
ListMetaData meta = result.meta;
int currentPage = meta.currentPage;
int totalPages = meta.lastPage;
int? totalItems = meta.total;
int? itemsPerPage = meta.perPage;
int? fromItem = meta.from;
int? toItem = meta.to;

Order Types #

For search queries, you can specify the order type:

// Ascending order (default)
OrderType.asc

// Descending order
OrderType.desc

Path Parameters #

Use curly braces {} in custom paths to define parameters:

// Define path with parameters
customPath: 'users/{userId}/categories/{categoryId}/items'

// Replace parameters
pathParams: {
  'userId': 123,
  'categoryId': 'electronics'
}

// Results in: users/123/categories/electronics/items

Data Models #

PaginatedData

Contains paginated results and metadata:

class PaginatedData<T> {
  List<T> data;        // The actual data items
  ListMetaData meta;   // Pagination metadata
}

ListMetaData

Pagination information:

class ListMetaData {
  int currentPage;    // Current page number
  int? from;         // First item number on current page
  int lastPage;      // Total number of pages
  int? perPage;      // Items per page
  int? to;           // Last item number on current page
  int? total;        // Total number of items
}

OrderType Enum

Available ordering options:

enum OrderType { 
  asc,   // Ascending order
  desc   // Descending order
}

JSON Structure for Pagination #

Paging queries expect a specific response format:

{
    "data": [
        {
            "id": 1,
            "name": "Item 1"
        },
        {
            "id": 2,
            "name": "Item 2"
        }
    ],
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 2,
        "per_page": 10,
        "to": 10,
        "total": 15
    } 
}

For non-paginated responses, you can return just the data array:

[
    {
        "id": 1,
        "name": "Item 1"
    }
]

Advanced Usage Examples #

Nested Resource Management

// Managing user payments
final paymentProvider = IwsHttpModel<Payment>(
    path: 'users/{userId}/payments',
    iwsHttp: IwsHttp(),
    fromJson: Payment.fromJson,
    toJson: Payment.toJson
);

// Get user's payments
PaginatedData<Payment> payments = await paymentProvider.fetchPaginated(
    pathParams: {'userId': 123},
    page: 1
);

// Create new payment for user
Payment newPayment = Payment(amount: 100.0, method: 'credit_card');
Payment created = await paymentProvider.add(
    newPayment,
    pathParams: {'userId': 123}
);

Custom Search with Complex Filters

// Advanced search with multiple filters
PaginatedData<Product> products = await productProvider.fetchPaginatedQuery(
    page: 1,
    orderBy: 'price',
    orderType: OrderType.asc,
    body: {
        'search': 'smartphone',
        'filters': {
            'category': 'electronics',
            'price_range': {
                'min': 200,
                'max': 1000
            },
            'brand': ['Apple', 'Samsung'],
            'in_stock': true
        },
        'date_range': {
            'from': '2024-01-01',
            'to': '2024-12-31'
        }
    }
);

Error Handling

try {
    MyModelClass model = await myModelProvider.get(999);
} on IwsHttpException catch (e) {
    // Handle HTTP errors (404, 500, etc.)
    print('HTTP Error: ${e.statusCode} - ${e.message}');
} catch (e) {
    // Handle other errors
    print('Error: $e');
}

Custom Result Attribute

If your API returns data in a different attribute:

final customProvider = IwsHttpModel<MyModel>(
    path: 'models',
    iwsHttp: IwsHttp(),
    fromJson: MyModel.fromJson,
    toJson: MyModel.toJson,
    resultAttribute: 'result' // API returns {"result": {...}}
);

Best Practices #

  1. Reuse IwsHttpModel instances: Create them once and reuse throughout your app
  2. Use path parameters: For dynamic routes, prefer path parameters over custom paths
  3. Handle pagination: Always check meta.lastPage when implementing infinite scroll
  4. Error handling: Wrap HTTP calls in try-catch blocks
  5. Type safety: Define proper model classes with fromJson and toJson methods

Integration with State Management #

With Provider

class MyModelNotifier extends ChangeNotifier {
  final IwsHttpModel<MyModel> _modelProvider;
  List<MyModel> _models = [];
  
  MyModelNotifier(this._modelProvider);
  
  Future<void> loadModels() async {
    try {
      final result = await _modelProvider.fetchPaginated();
      _models = result.data;
      notifyListeners();
    } catch (e) {
      // Handle error
    }
  }
}

With BLoC

class MyModelBloc extends Bloc<MyModelEvent, MyModelState> {
  final IwsHttpModel<MyModel> modelProvider;
  
  MyModelBloc(this.modelProvider) : super(MyModelInitial()) {
    on<LoadModels>(_onLoadModels);
  }
  
  Future<void> _onLoadModels(LoadModels event, Emitter<MyModelState> emit) async {
    emit(MyModelLoading());
    try {
      final result = await modelProvider.fetchPaginated(page: event.page);
      emit(MyModelLoaded(result.data, result.meta));
    } catch (e) {
      emit(MyModelError(e.toString()));
    }
  }
}

Request Parameters #

The parameters for paging and ordering are sent in the request route as follows:

https://exampledomain.com/api/models?page=1&orderBy=name&orderType=asc&filter=active

For POST requests with search body:

POST https://exampledomain.com/api/models/search?page=1&orderBy=created_at&orderType=desc
Content-Type: application/json

{
    "search": "search term",
    "filters": {
        "status": "active",
        "category": "electronics"
    }
}
0
likes
0
points
31
downloads

Publisher

unverified uploader

Weekly Downloads

Library for HTTP requests with the common operations CRUD, pagination and error handling.

Homepage

License

unknown (license)

Dependencies

flutter, iws_http

More

Packages that depend on iws_http_model