Developed by 🦏 zoocityboy

Manifest Dart SDK

Dart Pub pub points ci CodeFactor License: MIT

A Dart client SDK for interacting with Manifest backend services. This SDK provides a clean and intuitive interface for communication with your Manifest backend, handling authentication, CRUD operations, and file uploads.

Features

  • 🔐 Authentication - Login, signup, and logout functionality
  • 📝 Singles Management - Get and update single entities
  • 📋 Collections Management - Full CRUD operations on collection entities
  • 📎 File Uploads - Upload files and images
  • 🖼️ Image Processing - Handle image uploads with multiple sizes
  • 📄 Pagination Support - Paginate through large collections

Installation

Add this package to your project's dependencies:

dependencies:
  manifest_dart_sdk: 

Then run:

dart pub get

Usage

Initialize the client

import 'package:manifest-dart-sdk/manifest-dart-sdk.dart';

void main() {
  // Default URL is http://localhost:1111
  final client = Manifest();
  
  // Or specify a custom URL
  final customClient = Manifest('https://your-manifest-backend.com');
}

Working with Singles

Singles are standalone entities that don't belong to a collection.

// Get a single entity
var about = await client.single('about').get<Map<String, dynamic>>();
print('About page: ${about['title']}');

// Update a single entity (full replacement)
var updated = await client.single('about').update<Map<String, dynamic>>({
  'title': 'Updated About Page',
  'content': 'This is the updated about page content.'
});

// Partially update a single entity
var patched = await client.single('about').patch<Map<String, dynamic>>({
  'title': 'Patched About Page'
});

Working with Collections

Collections are groups of similar entities.

// Get a paginated list of items
var posts = await client.from('posts').find(page: 1, perPage: 10);
posts.data.forEach((post) {
  print('- ${post['title']}');
});

// Get a single item by ID
var post = await client.from('posts').findOneById(1);

// Create a new item
var newPost = await client.from('posts').create({
  'title': 'New Post',
  'content': 'This is a new post'
});

// Update an item (full replacement)
var updatedPost = await client.from('posts').update(1, {
  'title': 'Updated Post',
  'content': 'This post was updated'
});

// Partially update an item
var patchedPost = await client.from('posts').patch(1, {
  'title': 'Patched Post'
});

// Delete an item
int deletedId = await client.from('posts').delete(1);

Authentication

// Login
bool loggedIn = await client.login('users', 'user@example.com', 'password123');

// Get current user
var currentUser = await client.from('users').me();

// Logout
client.logout();

// Signup
bool signedUp = await client.signup('users', 'newuser@example.com', 'password123');

File Uploads

import 'dart:io';
import 'dart:typed_data';

// Upload a file
File file = File('document.pdf');
Uint8List fileBytes = await file.readAsBytes();
var uploadResult = await client.from('documents')
    .upload('attachment', fileBytes, 'document.pdf');
print('Uploaded file path: ${uploadResult['path']}');

// Upload an image
File imageFile = File('image.jpg');
Uint8List imageBytes = await imageFile.readAsBytes();
var imageResult = await client.from('posts')
    .uploadImage('featured_image', imageBytes, 'image.jpg');
print('Uploaded image paths: $imageResult');

// Get image URL by size
String imageUrl = client.imageUrl(imageResult, 'medium');

Error Handling

The SDK provides a robust exception hierarchy for proper error handling:

try {
  await client.from('posts').findOneById(999);
} on NotFoundException catch (e) {
  print('Post not found: ${e.message}');
} on AuthenticationException catch (e) {
  print('Authentication error: ${e.message}');
} on ValidationException catch (e) {
  print('Validation error:');
  if (e.validationErrors != null) {
    e.validationErrors!.forEach((field, errors) {
      print('  - $field: ${errors.join(', ')}');
    });
  }
} on ApiException catch (e) {
  print('API error (${e.statusCode}): ${e.message}');
} on NetworkException catch (e) {
  print('Network error: ${e.message}');
  print('Original exception: ${e.originalException}');
} on ManifestException catch (e) {
  print('General SDK error: ${e.message}');
} catch (e) {
  print('Unexpected error: $e');
}

Exception Types

The SDK throws the following exception types:

Exception Type Description Status Codes
NetworkException Network connectivity issues N/A
AuthenticationException Authentication issues 401, 403
ValidationException Validation errors 422
NotFoundException Resource not found 404
ServerException Server-side errors 500-599
RateLimitException Rate limit exceeded 429
ApiException Generic API errors Any error status code
ManifestException Base exception class N/A

Accessing Error Details

Most exception types provide additional error details:

try {
  // Operation that might fail
} on ApiException catch (e) {
  print('Status code: ${e.statusCode}');
  print('Error message: ${e.message}');
  print('Response body: ${e.body}');
  print('Error data: ${e.errorData}');
}

Validation errors provide field-specific error messages:

try {
  await client.from('posts').create({'incomplete': 'data'});
} on ValidationException catch (e) {
  e.validationErrors?.forEach((field, errors) {
    print('$field: ${errors.join(', ')}');
  });
}

Type Safety

You can use generics to get better type safety:

// Define a class for your entities
class Post {
  final int id;
  final String title;
  final String content;
  
  Post({required this.id, required this.title, required this.content});
  
  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      id: json['id'],
      title: json['title'],
      content: json['content'],
    );
  }
}

// Use the fromJson parameter with find to get typed objects
var posts = await client.from('posts').find<Post>(
  fromJson: (json) => Post.fromJson(json)
);

// Now posts.data contains a List<Post>
for (var post in posts.data) {
  print('Post ${post.id}: ${post.title}');
}

WASM Compatibility

This package is compatible with Dart's WebAssembly (WASM) target. All HTTP operations use the http package, which supports WASM and web environments. No dart:io dependencies are present.

Complete Example

See the /example folder for a complete example of using the SDK.

License

MIT

Libraries

manifest_dart_sdk
Manifest Dart SDK