easy_store 0.0.1 copy "easy_store: ^0.0.1" to clipboard
easy_store: ^0.0.1 copied to clipboard

A simple Flutter storage SDK. One unified API for SharedPreferences and SQLite — no boilerplate, no complexity.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:easy_store/easy_store.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await EasyStore.init(dbName: 'my_app.db');
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(title: 'EasyStore Demo', home: const ExamplePage());
  }
}

class ExamplePage extends StatefulWidget {
  const ExamplePage({super.key});
  @override
  State<ExamplePage> createState() => _ExamplePageState();
}

class _ExamplePageState extends State<ExamplePage> {
  // ── Shared Preferences controllers ──
  final _spKeyCtrl = TextEditingController();
  final _spValCtrl = TextEditingController();
  final _spGetKeyCtrl = TextEditingController();
  String _spType = 'String';
  String _spLog = '// output appears here';

  final _dbNameCtrl = TextEditingController(text: 'my_app.db');
  final _tblNameCtrl = TextEditingController(text: 'users');
  final _tblColsCtrl = TextEditingController(text: 'name:text, age:integer');
  final _insTblCtrl = TextEditingController(text: 'users');
  final _insDataCtrl = TextEditingController(text: 'name:Abanob, age:22');
  final _updTblCtrl = TextEditingController(text: 'users');
  final _updDataCtrl = TextEditingController(text: 'age:23');
  final _updIdCtrl = TextEditingController(text: '1');
  final _delTblCtrl = TextEditingController(text: 'users');
  final _delIdCtrl = TextEditingController(text: '1');
  String _dbLog = '// output appears here';
  List<Map<String, dynamic>> _rows = [];

  Future<void> _spSave() async {
    final key = _spKeyCtrl.text.trim();
    final val = _spValCtrl.text.trim();
    if (key.isEmpty || val.isEmpty) {
      setState(() => _spLog = '// key and value required');
      return;
    }
    try {
      switch (_spType) {
        case 'int':
          await EasyStore.shared.save(key, int.parse(val));
        case 'double':
          await EasyStore.shared.save(key, double.parse(val));
        case 'bool':
          await EasyStore.shared.save(key, val == 'true');
        default:
          await EasyStore.shared.save(key, val);
      }
      setState(() => _spLog = '✓ saved  "$key" = $val  ($_spType)');
    } catch (e) {
      setState(() => _spLog = '// error: $e');
    }
  }

  void _spGet() {
    final key = _spGetKeyCtrl.text.trim();
    if (key.isEmpty) {
      setState(() => _spLog = '// enter a key to get');
      return;
    }
    final value = EasyStore.shared.get(key);
    setState(
      () =>
          _spLog =
              value != null
                  ? '✓ get("$key")  →  $value'
                  : '// key "$key" not found',
    );
  }

  Future<void> _spDelete() async {
    final key = _spGetKeyCtrl.text.trim();
    if (key.isEmpty) {
      setState(() => _spLog = '// enter a key to delete');
      return;
    }
    await EasyStore.shared.delete(key);
    setState(() => _spLog = '✓ deleted  "$key"');
  }

  Future<void> _spClear() async {
    await EasyStore.shared.clear();
    setState(() => _spLog = '✓ cleared all keys');
  }

  // ─────────────────────────────────────────────
  // SQLite helpers
  // ─────────────────────────────────────────────

  Map<String, dynamic> _parseKV(String input) {
    final map = <String, dynamic>{};
    for (final pair in input.split(',')) {
      final parts = pair.trim().split(':');
      if (parts.length == 2) {
        final k = parts[0].trim();
        final v = parts[1].trim();
        map[k] = num.tryParse(v) ?? v;
      }
    }
    return map;
  }

  Map<String, ColumnType> _parseCols(String input) {
    final map = <String, ColumnType>{};
    for (final pair in input.split(',')) {
      final parts = pair.trim().split(':');
      if (parts.length == 2) {
        final name = parts[0].trim();
        final type = switch (parts[1].trim().toLowerCase()) {
          'integer' => ColumnType.integer,
          'real' => ColumnType.real,
          'blob' => ColumnType.blob,
          _ => ColumnType.text,
        };
        map[name] = type;
      }
    }
    return map;
  }

  void _appendDbLog(String msg) => setState(
    () => _dbLog = _dbLog == '// output appears here' ? msg : '$_dbLog\n$msg',
  );

  Future<void> _refreshRows(String table) async {
    try {
      final rows = await EasyStore.db.get(table);
      setState(() => _rows = rows);
    } catch (_) {
      setState(() => _rows = []);
    }
  }

  // ─────────────────────────────────────────────
  // SQLite operations
  // ─────────────────────────────────────────────

  Future<void> _createTable() async {
    final tbl = _tblNameCtrl.text.trim();
    final cols = _parseCols(_tblColsCtrl.text);
    try {
      await EasyStore.db.createTable(tbl, cols);
      _appendDbLog('✓ createTable("$tbl")');
      await _refreshRows(tbl);
    } catch (e) {
      _appendDbLog('// error: $e');
    }
  }

  Future<void> _insertRow() async {
    final tbl = _insTblCtrl.text.trim();
    final data = _parseKV(_insDataCtrl.text);
    try {
      final id = await EasyStore.db.insert(tbl, data);
      _appendDbLog('✓ insert → id: $id');
      await _refreshRows(tbl);
    } catch (e) {
      _appendDbLog('// error: $e');
    }
  }

  Future<void> _updateRow() async {
    final tbl = _updTblCtrl.text.trim();
    final data = _parseKV(_updDataCtrl.text);
    final id = int.tryParse(_updIdCtrl.text) ?? 0;
    try {
      await EasyStore.db.updateById(tbl, id, data);
      _appendDbLog('✓ updateById("$tbl", $id)');
      await _refreshRows(tbl);
    } catch (e) {
      _appendDbLog('// error: $e');
    }
  }

  Future<void> _deleteRow() async {
    final tbl = _delTblCtrl.text.trim();
    final id = int.tryParse(_delIdCtrl.text) ?? 0;
    try {
      await EasyStore.db.deleteById(tbl, id);
      _appendDbLog('✓ deleteById("$tbl", $id)');
      await _refreshRows(tbl);
    } catch (e) {
      _appendDbLog('// error: $e');
    }
  }

  // ─────────────────────────────────────────────
  // UI helpers
  // ─────────────────────────────────────────────

  Widget _sectionLabel(String text) => Padding(
    padding: const EdgeInsets.only(bottom: 6),
    child: Text(
      text,
      style: const TextStyle(
        fontSize: 11,
        fontWeight: FontWeight.w600,
        letterSpacing: 0.5,
        color: Colors.grey,
      ),
    ),
  );

  Widget _logBox(String log) => Container(
    width: double.infinity,
    padding: const EdgeInsets.all(12),
    decoration: BoxDecoration(
      color: Colors.grey.shade100,
      borderRadius: BorderRadius.circular(8),
    ),
    child: Text(
      log,
      style: const TextStyle(fontFamily: 'monospace', fontSize: 12),
    ),
  );

  Widget _card({
    required String title,
    required String badge,
    required Color badgeColor,
    required Widget child,
  }) => Card(
    margin: const EdgeInsets.only(bottom: 16),
    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
    elevation: 0,
    color: Colors.white,
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Container(
          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
          decoration: const BoxDecoration(
            border: Border(bottom: BorderSide(color: Color(0xFFE5E7EB))),
          ),
          child: Row(
            children: [
              Text(
                title,
                style: const TextStyle(
                  fontWeight: FontWeight.w600,
                  fontSize: 14,
                ),
              ),
              const SizedBox(width: 8),
              Container(
                padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
                decoration: BoxDecoration(
                  color: badgeColor.withOpacity(0.12),
                  borderRadius: BorderRadius.circular(20),
                ),
                child: Text(
                  badge,
                  style: TextStyle(
                    fontSize: 11,
                    color: badgeColor,
                    fontWeight: FontWeight.w600,
                  ),
                ),
              ),
            ],
          ),
        ),
        Padding(padding: const EdgeInsets.all(16), child: child),
      ],
    ),
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFF3F4F6),
      appBar: AppBar(
        title: const Text('EasyStore Demo'),
        backgroundColor: Colors.white,
        foregroundColor: Colors.black,
        elevation: 0,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // ── Shared Preferences Card ──────────────────
            _card(
              title: 'Shared Preferences',
              badge: 'EasyStore.shared',
              badgeColor: Colors.blue,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  _sectionLabel('SAVE'),
                  Row(
                    children: [
                      Expanded(
                        child: TextField(
                          controller: _spKeyCtrl,
                          decoration: const InputDecoration(
                            labelText: 'Key',
                            isDense: true,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      Expanded(
                        child: TextField(
                          controller: _spValCtrl,
                          decoration: const InputDecoration(
                            labelText: 'Value',
                            isDense: true,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      DropdownButton<String>(
                        value: _spType,
                        isDense: true,
                        items:
                            ['String', 'int', 'double', 'bool']
                                .map(
                                  (t) => DropdownMenuItem(
                                    value: t,
                                    child: Text(
                                      t,
                                      style: const TextStyle(fontSize: 13),
                                    ),
                                  ),
                                )
                                .toList(),
                        onChanged: (v) => setState(() => _spType = v!),
                      ),
                      const SizedBox(width: 8),
                      ElevatedButton(
                        onPressed: _spSave,
                        child: const Text('Save'),
                      ),
                    ],
                  ),
                  const Divider(height: 24),
                  _sectionLabel('GET / DELETE'),
                  Row(
                    children: [
                      Expanded(
                        child: TextField(
                          controller: _spGetKeyCtrl,
                          decoration: const InputDecoration(
                            labelText: 'Key',
                            isDense: true,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      ElevatedButton(
                        onPressed: _spGet,
                        child: const Text('Get'),
                      ),
                      const SizedBox(width: 8),
                      OutlinedButton(
                        onPressed: _spDelete,
                        style: OutlinedButton.styleFrom(
                          foregroundColor: Colors.red,
                        ),
                        child: const Text('Delete'),
                      ),
                      const SizedBox(width: 8),
                      OutlinedButton(
                        onPressed: _spClear,
                        style: OutlinedButton.styleFrom(
                          foregroundColor: Colors.red,
                        ),
                        child: const Text('Clear all'),
                      ),
                    ],
                  ),
                  const SizedBox(height: 12),
                  _logBox(_spLog),
                ],
              ),
            ),

            // ── SQLite Card ──────────────────────────────
            _card(
              title: 'SQLite',
              badge: 'EasyStore.db',
              badgeColor: Colors.green,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  // Create Table
                  _sectionLabel('CREATE TABLE'),
                  Row(
                    children: [
                      Expanded(
                        child: TextField(
                          controller: _tblNameCtrl,
                          decoration: const InputDecoration(
                            labelText: 'Table name',
                            isDense: true,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      Expanded(
                        flex: 2,
                        child: TextField(
                          controller: _tblColsCtrl,
                          decoration: const InputDecoration(
                            labelText: 'Columns (name:type, ...)',
                            isDense: true,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      ElevatedButton(
                        onPressed: _createTable,
                        child: const Text('Create'),
                      ),
                    ],
                  ),
                  const Divider(height: 24),

                  // Insert
                  _sectionLabel('INSERT'),
                  Row(
                    children: [
                      Expanded(
                        child: TextField(
                          controller: _insTblCtrl,
                          decoration: const InputDecoration(
                            labelText: 'Table',
                            isDense: true,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      Expanded(
                        flex: 2,
                        child: TextField(
                          controller: _insDataCtrl,
                          decoration: const InputDecoration(
                            labelText: 'Data (key:value, ...)',
                            isDense: true,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      ElevatedButton(
                        onPressed: _insertRow,
                        child: const Text('Insert'),
                      ),
                    ],
                  ),
                  const Divider(height: 24),

                  // Update
                  _sectionLabel('UPDATE'),
                  Row(
                    children: [
                      Expanded(
                        child: TextField(
                          controller: _updTblCtrl,
                          decoration: const InputDecoration(
                            labelText: 'Table',
                            isDense: true,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      Expanded(
                        flex: 2,
                        child: TextField(
                          controller: _updDataCtrl,
                          decoration: const InputDecoration(
                            labelText: 'New data (key:value, ...)',
                            isDense: true,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      SizedBox(
                        width: 70,
                        child: TextField(
                          controller: _updIdCtrl,
                          keyboardType: TextInputType.number,
                          decoration: const InputDecoration(
                            labelText: 'ID',
                            isDense: true,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      ElevatedButton(
                        onPressed: _updateRow,
                        child: const Text('Update'),
                      ),
                    ],
                  ),
                  const Divider(height: 24),

                  // Delete
                  _sectionLabel('DELETE'),
                  Row(
                    children: [
                      Expanded(
                        child: TextField(
                          controller: _delTblCtrl,
                          decoration: const InputDecoration(
                            labelText: 'Table',
                            isDense: true,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      SizedBox(
                        width: 70,
                        child: TextField(
                          controller: _delIdCtrl,
                          keyboardType: TextInputType.number,
                          decoration: const InputDecoration(
                            labelText: 'ID',
                            isDense: true,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      OutlinedButton(
                        onPressed: _deleteRow,
                        style: OutlinedButton.styleFrom(
                          foregroundColor: Colors.red,
                        ),
                        child: const Text('Delete'),
                      ),
                    ],
                  ),
                  const Divider(height: 24),

                  // Results table
                  _sectionLabel('RESULTS'),
                  if (_rows.isEmpty)
                    const Text(
                      'No data yet — insert some rows',
                      style: TextStyle(color: Colors.grey, fontSize: 13),
                    )
                  else
                    SingleChildScrollView(
                      scrollDirection: Axis.horizontal,
                      child: DataTable(
                        headingRowHeight: 36,
                        dataRowMinHeight: 32,
                        dataRowMaxHeight: 40,
                        columns:
                            _rows.first.keys
                                .map(
                                  (k) => DataColumn(
                                    label: Text(
                                      k,
                                      style: const TextStyle(
                                        fontSize: 12,
                                        fontWeight: FontWeight.w600,
                                      ),
                                    ),
                                  ),
                                )
                                .toList(),
                        rows:
                            _rows
                                .map(
                                  (row) => DataRow(
                                    cells:
                                        row.values
                                            .map(
                                              (v) => DataCell(
                                                Text(
                                                  '$v',
                                                  style: const TextStyle(
                                                    fontSize: 13,
                                                  ),
                                                ),
                                              ),
                                            )
                                            .toList(),
                                  ),
                                )
                                .toList(),
                      ),
                    ),
                  const SizedBox(height: 12),
                  _logBox(_dbLog),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
1
likes
160
points
27
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A simple Flutter storage SDK. One unified API for SharedPreferences and SQLite — no boilerplate, no complexity.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, path, shared_preferences, sqflite

More

Packages that depend on easy_store