smithery/Kaakati

GetStorage Patterns

Local storage with GetStorage for preferences, caching, and offline-first patterns

Installation

$ npx skills add smithery/Kaakati --skill getstorage-patterns

Also in this package

Other skills from smithery/Kaakati · top by installs.

npx skills add smithery/Kaakati

Browse all from smithery/Kaakati

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.0

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 4,367 B
  • docs SUMMARY.md 109 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

GetStorage Patterns

Initialization

// main.dart
void main() async {
  await GetStorage.init();
  runApp(MyApp());
}

Storage Service Pattern

class StorageService {
  final GetStorage _box;
  
  StorageService() : _box = GetStorage();
  
  // Token management
  String? get token => _box.read<String>('auth_token');
  Future<void> setToken(String token) => _box.write('auth_token', token);
  Future<void> clearToken() => _box.remove('auth_token');
  
  // User data
  Map<String, dynamic>? get userData => _box.read<Map<String, dynamic>>('user_data');
  Future<void> setUserData(Map<String, dynamic> data) => _box.write('user_data', data);
  
  // Preferences
  bool get isDarkMode => _box.read<bool>('dark_mode') ?? false;
  Future<void> setDarkMode(bool value) => _box.write('dark_mode', value);
  
  String get locale => _box.read<String>('locale') ?? 'en';
  Future<void> setLocale(String locale) => _box.write('locale', locale);
  
  // Clear all
  Future<void> clearAll() => _box.erase();
  
  // Listen to changes
  void listenKey(String key, Function(dynamic) callback) {
    _box.listenKey(key, callback);
  }
}

Local Data Source Pattern

class UserLocalDataSource {
  final GetStorage _storage;
  static const String _usersKey = 'cached_users';
  static const String _userKeyPrefix = 'cached_user_';
  static const Duration _cacheDuration = Duration(hours: 24);
  
  UserLocalDataSource(this._storage);
  
  Future<void> cacheUser(UserModel user) async {
    final cacheData = {
      'user': user.toJson(),
      'timestamp': DateTime.now().toIso8601String(),
    };
    await _storage.write('$_userKeyPrefix${user.id}', cacheData);
  }
  
  Future<UserModel?> getCachedUser(String id) async {
    final cacheData = _storage.read<Map<String, dynamic>>('$_userKeyPrefix$id');
    
    if (cacheData == null) return null;
    
    // Check cache expiration
    final timestamp = DateTime.parse(cacheData['timestamp']);
    if (DateTime.now().difference(timestamp) > _cacheDuration) {
      await _storage.remove('$_userKeyPrefix$id');
      return null;
    }
    
    return UserModel.fromJson(cacheData['user']);
  }
  
  Future<void> cacheUsers(List<UserModel> users) async {
    final cacheData = {
      'users': users.map((u) => u.toJson()).toList(),
      'timestamp': DateTime.now().toIso8601String(),
    };
    await _storage.write(_usersKey, cacheData);
  }
  
  Future<List<UserModel>?> getCachedUsers() async {
    final cacheData = _storage.read<Map<String, dynamic>>(_usersKey);
    
    if (cacheData == null) return null;
    
    final timestamp = DateTime.parse(cacheData['timestamp']);
    if (DateTime.now().difference(timestamp) > _cacheDuration) {
      await _storage.remove(_usersKey);
      return null;
    }
    
    final List<dynamic> usersList = cacheData['users'];
    return usersList.map((json) => UserModel.fromJson(json)).toList();
  }
  
  Future<void> clearCache() async {
    await _storage.erase();
  }
}

GetX Service Integration

class CacheService extends GetxService {
  final GetStorage _storage;
  
  CacheService() : _storage = GetStorage();
  
  Future<CacheService> init() async {
    await GetStorage.init();
    return this;
  }
  
  // Reactive cache
  final _cachedData = <String, dynamic>{}.obs;
  
  T? get<T>(String key) {
    return _storage.read<T>(key);
  }
  
  Future<void> put<T>(String key, T value, {Duration? expiry}) async {
    if (expiry != null) {
      final expiryData = {
        'value': value,
        'expiry': DateTime.now().add(expiry).toIso8601String(),
      };
      await _storage.write(key, expiryData);
    } else {
      await _storage.write(key, value);
    }
    _cachedData[key] = value;
  }
  
  Future<void> remove(String key) async {
    await _storage.remove(key);
    _cachedData.remove(key);
  }
  
  bool has(String key) {
    return _storage.hasData(key);
  }
}

Best Practices

  • Initialize GetStorage before running app
  • Use type-safe reads (read<String>, read<int>, etc.)
  • Implement cache expiration for time-sensitive data
  • Clear cache on logout
  • Use separate keys for different data types
  • Listen to changes for reactive updates