Basics

स्टोरेज

परिचय

Nylo Website v7 NyStorage क्लास के माध्यम से एक शक्तिशाली स्टोरेज सिस्टम प्रदान करता है। यह यूज़र के डिवाइस पर डेटा को सुरक्षित रूप से स्टोर करने के लिए अंदरूनी तौर पर flutter_secure_storage का उपयोग करता है।

import 'package:nylo_framework/nylo_framework.dart';

// Save a value
await NyStorage.save("coins", 100);

// Read a value
int? coins = await NyStorage.read<int>('coins'); // 100

// Delete a value
await NyStorage.delete('coins');

वैल्यू सेव करना

NyStorage.save() या storageSave() हेल्पर का उपयोग करके वैल्यू सेव करें:

// Using NyStorage class
await NyStorage.save("username", "Anthony");
await NyStorage.save("score", 1500);
await NyStorage.save("isPremium", true);

// Using helper function
await storageSave("username", "Anthony");

Backpack में एक साथ सेव करें

पर्सिस्टेंट स्टोरेज और इन-मेमोरी Backpack दोनों में स्टोर करें:

await NyStorage.save('auth_token', 'abc123', inBackpack: true);

// Now accessible synchronously via Backpack
String? token = Backpack.instance.read('auth_token');

वैल्यू पढ़ना

ऑटोमैटिक टाइप कास्टिंग के साथ वैल्यू पढ़ें:

// Read as String (default)
String? username = await NyStorage.read('username');

// Read with type casting
int? score = await NyStorage.read<int>('score');
double? rating = await NyStorage.read<double>('rating');
bool? isPremium = await NyStorage.read<bool>('isPremium');

// With default value
String name = await NyStorage.read('name', defaultValue: 'Guest') ?? 'Guest';

// Using helper function
String? username = await storageRead('username');
int? score = await storageRead<int>('score');

वैल्यू डिलीट करना

// Delete a single key
await NyStorage.delete('username');

// Delete and remove from Backpack too
await NyStorage.delete('auth_token', andFromBackpack: true);

// Delete multiple keys
await NyStorage.deleteMultiple(['key1', 'key2', 'key3']);

// Delete all (with optional exclusions)
await NyStorage.deleteAll();
await NyStorage.deleteAll(excludeKeys: ['auth_token']);

स्टोरेज कीज़

अपनी स्टोरेज कीज़ को lib/config/storage_keys.dart में व्यवस्थित करें:

final class StorageKeysConfig {
  // Auth key for user authentication
  static StorageKey auth = 'SK_AUTH';

  // Keys synced on app boot
  static syncedOnBoot() => () async {
    return [
      coins.defaultValue(0),
      themePreference.defaultValue('light'),
    ];
  };

  static StorageKey coins = 'SK_COINS';
  static StorageKey themePreference = 'SK_THEME_PREFERENCE';
  static StorageKey onboardingComplete = 'SK_ONBOARDING_COMPLETE';
}

StorageKey एक्सटेंशन का उपयोग

StorageKey String के लिए एक typedef है, और इसमें शक्तिशाली एक्सटेंशन मेथड्स का एक सेट है:

// Save
await StorageKeysConfig.coins.save(100);

// Save with Backpack
await StorageKeysConfig.coins.save(100, inBackpack: true);

// Read
int? coins = await StorageKeysConfig.coins.read<int>();

// Read with default value
int? coins = await StorageKeysConfig.coins.fromStorage<int>(defaultValue: 0);

// Save/Read JSON
await StorageKeysConfig.coins.saveJson({"gold": 50, "silver": 200});
Map? data = await StorageKeysConfig.coins.readJson<Map>();

// Delete
await StorageKeysConfig.coins.deleteFromStorage();

// Delete (alias)
await StorageKeysConfig.coins.flush();

// Read from Backpack (synchronous)
int? coins = StorageKeysConfig.coins.fromBackpack<int>();

// Collection operations
await StorageKeysConfig.coins.addToCollection<int>(100);
List<int> allCoins = await StorageKeysConfig.coins.readCollection<int>();

JSON सेव/पढ़ना

JSON डेटा स्टोर और प्राप्त करें:

// Save JSON
Map<String, dynamic> user = {
  "name": "Anthony",
  "email": "anthony@example.com",
  "preferences": {"theme": "dark"}
};
await NyStorage.saveJson("user_data", user);

// Read JSON
Map<String, dynamic>? userData = await NyStorage.readJson("user_data");
print(userData?['name']); // "Anthony"

TTL (टाइम-टू-लिव)

Nylo Website v7 ऑटोमैटिक एक्सपायरेशन के साथ वैल्यू स्टोर करने का समर्थन करता है:

// Save with 1 hour expiration
await NyStorage.saveWithExpiry(
  'session_token',
  'abc123',
  ttl: Duration(hours: 1),
);

// Read (returns null if expired)
String? token = await NyStorage.readWithExpiry<String>('session_token');

// Check remaining time
Duration? remaining = await NyStorage.getTimeToLive('session_token');
if (remaining != null) {
  print('Expires in ${remaining.inMinutes} minutes');
}

// Clean up all expired keys
int removed = await NyStorage.removeExpired();
print('Removed $removed expired keys');

बैच ऑपरेशन्स

एकाधिक स्टोरेज ऑपरेशन्स को कुशलतापूर्वक हैंडल करें:

// Save multiple values
await NyStorage.saveAll({
  'username': 'Anthony',
  'score': 1500,
  'level': 10,
});

// Read multiple values
Map<String, dynamic?> values = await NyStorage.readMultiple<dynamic>([
  'username',
  'score',
  'level',
]);

// Delete multiple keys
await NyStorage.deleteMultiple(['temp_1', 'temp_2', 'temp_3']);

कलेक्शन्स का परिचय

कलेक्शन्स आपको एक कुंजी के तहत आइटम्स की सूची स्टोर करने की अनुमति देते हैं:

// Add items to a collection
await NyStorage.addToCollection("favorites", item: "Product A");
await NyStorage.addToCollection("favorites", item: "Product B");

// Read the collection
List<String> favorites = await NyStorage.readCollection<String>("favorites");
// ["Product A", "Product B"]

कलेक्शन में जोड़ना

// Add item (allows duplicates by default)
await NyStorage.addToCollection("cart_ids", item: 123);

// Prevent duplicates
await NyStorage.addToCollection(
  "cart_ids",
  item: 123,
  allowDuplicates: false,
);

// Save entire collection at once
await NyStorage.saveCollection<int>("cart_ids", [1, 2, 3, 4, 5]);

कलेक्शन पढ़ना

// Read collection with type
List<int> cartIds = await NyStorage.readCollection<int>("cart_ids");

// Check if collection is empty
bool isEmpty = await NyStorage.isCollectionEmpty("cart_ids");

कलेक्शन अपडेट करना

// Update item by index
await NyStorage.updateCollectionByIndex<int>(
  0, // index
  (item) => item + 10, // transform function
  key: "scores",
);

// Update items matching a condition
await NyStorage.updateCollectionWhere<Map<String, dynamic>>(
  (item) => item['id'] == 5, // where condition
  key: "products",
  update: (item) {
    item['quantity'] = item['quantity'] + 1;
    return item;
  },
);

कलेक्शन से डिलीट करना

// Delete by index
await NyStorage.deleteFromCollection<String>(0, key: "favorites");

// Delete by value
await NyStorage.deleteValueFromCollection<int>(
  "cart_ids",
  value: 123,
);

// Delete items matching a condition
await NyStorage.deleteFromCollectionWhere<Map<String, dynamic>>(
  (item) => item['expired'] == true,
  key: "coupons",
);

// Delete entire collection
await NyStorage.delete("favorites");

Backpack स्टोरेज

Backpack यूज़र के सेशन के दौरान त्वरित सिंक्रोनस एक्सेस के लिए एक हल्का इन-मेमोरी स्टोरेज क्लास है। ऐप बंद होने पर डेटा पर्सिस्ट नहीं होता।

Backpack में सेव करें

// Using helper
backpackSave('user_token', 'abc123');
backpackSave('user', userObject);

// Using Backpack directly
Backpack.instance.save('settings', {'darkMode': true});

Backpack से पढ़ें

// Using helper
String? token = backpackRead('user_token');
User? user = backpackRead<User>('user');

// Using Backpack directly
var settings = Backpack.instance.read('settings');

Backpack से डिलीट करें

backpackDelete('user_token');

// Delete all
backpackDeleteAll();

व्यावहारिक उदाहरण

// After login, store token in both persistent and session storage
Future<void> handleLogin(String token) async {
  // Persist for app restarts
  await NyStorage.save('auth_token', token);

  // Also store in Backpack for quick access
  backpackSave('auth_token', token);
}

// In API service, access synchronously
class ApiService extends NyApiService {
  Future<User?> getProfile() async {
    return await network<User>(
      request: (request) => request.get("/profile"),
      bearerToken: backpackRead('auth_token'), // No await needed
    );
  }
}

Backpack के साथ पर्सिस्ट करना

पर्सिस्टेंट स्टोरेज और Backpack दोनों में एक कॉल में स्टोर करें:

// Save to both
await NyStorage.save('user_token', 'abc123', inBackpack: true);

// Now accessible via Backpack (sync) and NyStorage (async)
String? tokenSync = Backpack.instance.read('user_token');
String? tokenAsync = await NyStorage.read('user_token');

स्टोरेज को Backpack में सिंक करना

ऐप बूट पर सभी पर्सिस्टेंट स्टोरेज को Backpack में लोड करें:

// In your app provider
await NyStorage.syncToBackpack();

// With overwrite option
await NyStorage.syncToBackpack(overwrite: true);

सेशन्स

सेशन्स संबंधित डेटा को ग्रुप करने के लिए नेम्ड, इन-मेमोरी स्टोरेज प्रदान करते हैं (पर्सिस्ट नहीं होता):

// Create/access a session and add data
session('checkout')
    .add('items', ['Product A', 'Product B'])
    .add('total', 99.99)
    .add('coupon', 'SAVE10');

// Or initialize with data
session('checkout', {
  'items': ['Product A', 'Product B'],
  'total': 99.99,
});

// Read session data
List<String>? items = session('checkout').get<List<String>>('items');
double? total = session('checkout').get<double>('total');

// Get all session data
Map<String, dynamic>? checkoutData = session('checkout').data();

// Delete a single value
session('checkout').delete('coupon');

// Clear entire session
session('checkout').clear();
// or
session('checkout').flush();

सेशन्स पर्सिस्ट करना

सेशन्स को पर्सिस्टेंट स्टोरेज में सिंक किया जा सकता है:

// Save session to storage
await session('checkout').syncToStorage();

// Restore session from storage
await session('checkout').syncFromStorage();

सेशन उपयोग के मामले

सेशन्स इनके लिए आदर्श हैं:

  • मल्टी-स्टेप फ़ॉर्म्स (ऑनबोर्डिंग, चेकआउट)
  • अस्थायी यूज़र प्रेफ़रेंसेस
  • विज़ार्ड/जर्नी फ़्लोज़
  • शॉपिंग कार्ट डेटा

मॉडल सेव

Model बेस क्लास बिल्ट-इन स्टोरेज मेथड्स प्रदान करती है। जब आप कंस्ट्रक्टर में key परिभाषित करते हैं, तो मॉडल खुद को सेव कर सकता है:

class User extends Model {
  String? name;
  String? email;

  // Define a storage key
  static StorageKey key = 'user';
  User() : super(key: key);

  User.fromJson(dynamic data) : super(key: key) {
    name = data['name'];
    email = data['email'];
  }

  @override
  Map<String, dynamic> toJson() => {
    "name": name,
    "email": email,
  };
}

मॉडल सेव करना

User user = User();
user.name = "Anthony";
user.email = "anthony@example.com";

// Save to persistent storage
await user.save();

// Save to both storage and Backpack
await user.save(inBackpack: true);

मॉडल वापस पढ़ना

User? user = await NyStorage.read<User>(User.key);

Backpack में सिंक करना

सिंक्रोनस एक्सेस के लिए स्टोरेज से मॉडल को Backpack में लोड करें:

bool found = await User().syncToBackpack();
if (found) {
  User? user = Backpack.instance.read<User>(User.key);
}

मॉडल कलेक्शन्स

मॉडल्स को कलेक्शन में सेव करें:

User userAnthony = User();
userAnthony.name = 'Anthony';
await userAnthony.saveToCollection();

User userKyle = User();
userKyle.name = 'Kyle';
await userKyle.saveToCollection();

// Read back
List<User> users = await NyStorage.readCollection<User>(User.key);

StorageKey एक्सटेंशन रेफ़रेंस

StorageKey String के लिए एक typedef है। NyStorageKeyExt एक्सटेंशन ये मेथड्स प्रदान करता है:

मेथड रिटर्न विवरण
save(value, {inBackpack}) Future स्टोरेज में वैल्यू सेव करें
saveJson(value, {inBackpack}) Future स्टोरेज में JSON वैल्यू सेव करें
read<T>({defaultValue}) Future<T?> स्टोरेज से वैल्यू पढ़ें
readJson<T>({defaultValue}) Future<T?> स्टोरेज से JSON वैल्यू पढ़ें
fromStorage<T>({defaultValue}) Future<T?> read का एलियास
fromBackpack<T>({defaultValue}) T? Backpack से पढ़ें (सिंक)
toModel<T>() T JSON स्ट्रिंग को मॉडल में कन्वर्ट करें
addToCollection<T>(value, {allowDuplicates}) Future कलेक्शन में आइटम जोड़ें
readCollection<T>() Future<List<T>> कलेक्शन पढ़ें
deleteFromStorage({andFromBackpack}) Future स्टोरेज से डिलीट करें
flush({andFromBackpack}) Future deleteFromStorage का एलियास
defaultValue<T>(value) Future Function(bool)? कुंजी खाली होने पर डिफ़ॉल्ट सेट करें (syncedOnBoot में उपयोग)

स्टोरेज एक्सेप्शन्स

Nylo Website v7 टाइप्ड स्टोरेज एक्सेप्शन्स प्रदान करता है:

एक्सेप्शन विवरण
StorageException मैसेज और वैकल्पिक कुंजी के साथ बेस एक्सेप्शन
StorageSerializationException स्टोरेज के लिए ऑब्जेक्ट सीरियलाइज़ करने में विफल
StorageDeserializationException स्टोर किए गए डेटा को डीसीरियलाइज़ करने में विफल
StorageKeyNotFoundException स्टोरेज कुंजी नहीं मिली
StorageTimeoutException स्टोरेज ऑपरेशन टाइमआउट हो गया
try {
  await NyStorage.read<User>('user');
} on StorageDeserializationException catch (e) {
  print('Failed to load user: ${e.message}');
  print('Expected type: ${e.expectedType}');
}

लीगेसी माइग्रेशन

Nylo Website v7 एक नया एन्वेलप स्टोरेज फ़ॉर्मेट उपयोग करता है। यदि आप v6 से अपग्रेड कर रहे हैं, तो आप पुराने डेटा को माइग्रेट कर सकते हैं:

// Call during app initialization
int migrated = await NyStorage.migrateToEnvelopeFormat();
print('Migrated $migrated keys to new format');

यह लीगेसी फ़ॉर्मेट (अलग _runtime_type कुंजियाँ) को नए एन्वेलप फ़ॉर्मेट में कन्वर्ट करता है। माइग्रेशन को कई बार चलाना सुरक्षित है - पहले से माइग्रेट की गई कुंजियाँ छोड़ दी जाती हैं।