flutter_clean_storage

A robust, type-safe storage solution for Flutter applications built with clean architecture principles. This package provides a seamless way to handle both secure and non-secure storage needs with built-in support for various data types, JSON serialization, and list storage.

pub package likes popularity Flutter Tests

Features

  • πŸ”’ Secure and non-secure storage support
  • 🎯 Type-safe storage operations
  • 🧩 Built-in parsers for common types
  • πŸ“¦ JSON serialization support
  • πŸ“ List storage support
  • πŸ—οΈ Clean architecture approach
  • πŸ”„ Easy-to-use extensions
  • πŸ“± Cross-platform support

Installation

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

dependencies:
  flutter_clean_storage: ^0.0.1

Usage

Basic Usage

// Initialize the storage service
await CleanStorageService.instance.initialize();

// Create storage items
final counterStorage = 'counter'.asIntStorage();
final nameStorage = 'username'.asStorage();
final isDarkMode = 'darkMode'.asBoolStorage();

// Store values
await counterStorage.set(42);
await nameStorage.set('John Doe');
await isDarkMode.set(true);

// Retrieve values
final count = await counterStorage.get();
final name = await nameStorage.get();
final darkMode = await isDarkMode.get();

// Delete values
await counterStorage.delete();

Secure Storage

// Create secure storage items
final tokenStorage = 'auth_token'.asStorage(isSecure: true);
final pinCodeStorage = 'pin_code'.asStorage(isSecure: true);

// Store sensitive data securely
await tokenStorage.set('your-secret-token');
await pinCodeStorage.set('1234');

Custom Types

class User {
  final String name;
  final int age;

  User({required this.name, required this.age});

  factory User.fromJson(Map<String, dynamic> json) => User(
        name: json['name'] as String,
        age: json['age'] as int,
      );

  Map<String, dynamic> toJson() => {
        'name': name,
        'age': age,
      };
}

// Create a storage item for User
final userStorage = StorageItem<User>(
  key: 'current_user',
  defaultValue: User(name: '', age: 0),
  parser: StorageParsers.json(
    fromJson: User.fromJson,
    toJson: (user) => user.toJson(),
  ),
);

// Store user
await userStorage.set(User(name: 'John', age: 30));

// Retrieve user
final user = await userStorage.get();

List Storage

// Store list of strings
final favoriteColors = StorageItem<List<String>>(
  key: 'favorite_colors',
  defaultValue: const [],
  parser: StorageParsers.list(StorageParsers.string),
);

await favoriteColors.set(['red', 'blue', 'green']);

Extensions

// Create storage items using extensions
final counter = 'counter'.asIntStorage(defaultValue: 0);
final username = 'username'.asStorage(defaultValue: '');
final lastUpdate = 'lastUpdate'.asDateTimeStorage();

// Make any storage item secure
final secureToken = 'token'.asStorage().secure();

Advanced Usage

Update with Callback

final counterStorage = 'counter'.asIntStorage();

// Increment counter
await counterStorage.update((current) => current + 1);

Clearing Storage

// Clear non-secure storage
await CleanStorageService.instance.clearAll();

// Clear secure storage
await CleanStorageService.instance.clearAllSecure();

// Clear everything
await CleanStorageService.instance.clearEverything();

Static Storage Pattern

You can create a centralized storage management class using static members:

/// Application-wide storage management
class AppStorage {
  // Authentication & User Data
  static final authToken = StorageItem<String>(
    key: 'auth_token',
    defaultValue: '',
    parser: StorageParsers.string,
    isSecure: true,
  );

  static final currentUser = StorageItem<User?>(
    key: 'current_user',
    defaultValue: null,
    parser: StorageParsers.json<User?>(
      fromJson: (json) => json.isEmpty ? null : User.fromJson(json),
      toJson: (user) => user?.toJson() ?? {},
    ),
  );

  // App Settings
  static final themeMode = StorageItem<String>(
    key: 'theme_mode',
    defaultValue: 'system',
    parser: StorageParsers.string,
  );

  static final language = StorageItem<String>(
    key: 'language',
    defaultValue: 'en',
    parser: StorageParsers.string,
  );

  // Helper Methods
  static Future<void> initialize() async {
    await CleanStorageService.instance.initialize();
  }

  static Future<bool> isAuthenticated() async {
    final token = await authToken.get();
    final user = await currentUser.get();
    return token.isNotEmpty && user != null;
  }

  static Future<void> saveSession({
    required String token,
    required User user,
  }) async {
    await Future.wait([
      authToken.set(token),
      currentUser.set(user),
    ]);
  }

  static Future<void> clearSession() async {
    await Future.wait([
      authToken.delete(),
      currentUser.delete(),
    ]);
  }
}

Usage example:

// Initialize storage
await AppStorage.initialize();

// Check authentication
final isAuthenticated = await AppStorage.isAuthenticated();

// Save user session
await AppStorage.saveSession(
  token: 'your-auth-token',
  user: User(name: 'John', age: 30),
);

// Access individual storage items
final theme = await AppStorage.themeMode.get();
final language = await AppStorage.language.get();

// Clear session
await AppStorage.clearSession();

This pattern provides a clean and organized way to manage application-wide storage with proper separation of concerns.

Platform Support

Android iOS MacOS Web Linux Windows
βœ… βœ… βœ… βœ… βœ… βœ…

Maintainers

Contributing

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

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Please make sure to update tests as appropriate.

License

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