ejdb2_flutter 1.0.17+1

  • Readme
  • Changelog
  • Example
  • Installing
  • 76

EJDB2 Flutter integration #

Embeddable JSON Database engine http://ejdb.org Dart binding.

See https://github.com/Softmotions/ejdb/blob/master/README.md

For API usage examples take a look into /example application.

Example #

pubspec.yaml

dependencies:
  ejdb2_flutter:
import 'package:ejdb2_flutter/ejdb2_flutter.dart';

var db = await EJDB2Builder('test.db').open();

var id = await db.put('parrots', {'name': 'Bianca', 'age': 4});
  print('Bianca record: ${id}');

id = await db.put('parrots', {'name': 'Darko', 'age': 8});
print('Darko record: ${id}');

final q = db.createQuery('/[age > :age]', 'parrots');
await for (final doc in q.setInt('age', 3).execute()) {
  print('Found ${doc}');
}

await db.close();

Supported platforms #

  • iOS
  • Android

iOS notes #

In order to build app with this binding you have to add the following code into application Podfile:

pre_install do |installer|
  # workaround for https://github.com/CocoaPods/CocoaPods/issues/3289
  Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
end

Android notes #

For release builds you have to setup proguard rules as follows:

build.gradle

    buildTypes {
      ...
        release {
            ...
            minifyEnabled true
            useProguard true
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
    }

proguard-rules.pro

...

# Keep EJDB
-keep class com.softmotions.ejdb2.** { *; }

How build it manually #

git clone https://github.com/Softmotions/ejdb.git

cd ./ejdb
mkdir ./build && cd build

cmake .. -DCMAKE_BUILD_TYPE=Release \
         -DANDROID_NDK_HOME=<path to Android NDK> \
         -DBUILD_FLUTTER_BINDING=ON
make

# Move generate to ejdb2 flutter pub package with example app
cd src/bindings/ejdb2_flutter/pub_publish
flutter pub get
cd ./example

# Start Android emulator
flutter run

1.0.17+1 #

  • Upgraded to ejdb v2.0.43

1.0.16+1 #

  • Upgraded to ejdb v2.0.42

1.0.15+1 #

  • Upgraded to ejdb v2.0.41

1.0.14+2 #

  • Readme updated

1.0.14+1 #

  • Upgraded to ejdb v2.0.40

1.0.13+1 #

  • Upgraded to ejdb v2.0.39

1.0.12+1 #

  • Upgraded to ejdb v2.0.37
  • Fixed wal related durability issue

1.0.11+2 #

  • Readme updated

1.0.11+1 #

  • Added iOS support
  • Upgraded to ejdb v2.0.36

1.0.10+1 #

  • Fixed JQL apply ignores value set by placeholder #269

1.0.9+1 #

  • Reduced library size by 400K: stripped off unused utf8proc data

1.0.8+1 #

  • Added patchOrPut()

1.0.7+1 #

  • Added delIgnoreNotFound()

1.0.6+1 #

  • Upgraded to ejdb v2.0.32

1.0.5+1 #

  • Upgraded to ejdb v2.0.31

1.0.4+1 #

  • Added EJDB2#getOptional for convenience

1.0.3+1 #

  • Removed depenedency for eclipse generator plugin

1.0.2+1 #

  • Upgraded to ejdb v2.0.30

1.0.1+1 #

  • Minors: eliminated unchecked cast warning

1.0.0+2 #

  • Initial release

example/lib/main.dart

import 'dart:async';

import 'package:json_at/json_at.dart';
import 'package:ejdb2_example/utils/assertions.dart';
import 'package:ejdb2_flutter/ejdb2_flutter.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _result = '';

  @override
  void initState() {
    super.initState();
    _initTesting();
  }

  Future<void> _doTest() async {
    String dbpath;

    var db = await (EJDB2Builder('test.db')
          ..truncate = true
          ..walEnabled = true)
        .open();
    try {
      var id = await db.put('mycoll', {'foo': 'bar'});
      assertEqual(id, 1);

      JBDOC doc = await db.get('mycoll', id);
      assertDeepEqual(doc.object, {'foo': 'bar'});

      id = await db.put('mycoll', {'foo': 'baz'}, id);
      assertEqual(id, 1);

      doc = await db.get('mycoll', id);
      assertDeepEqual(doc.object, {'foo': 'baz'});

      dynamic error;
      try {
        await db.put('mycoll', '{"');
      } catch (e) {
        error = e;
      }
      assertNotNull(error);
      assertTrue(error is EJDB2Error);
      assertEqual(error.code, '@ejdb IWRC:86005');

      assertTrue('${error.message}'.contains('Unquoted JSON string (JBL_ERROR_PARSE_UNQUOTED_STRING)'));

      id = await db.put('mycoll', {'foo': 'bar'});
      assertEqual(id, 2);

      var list = await db.createQuery('@mycoll/*').list();
      assertEqual(list.toString(), '[JBDOC: 2 {"foo":"bar"}, JBDOC: 1 {"foo":"baz"}]');

      JBDOC first = await db.createQuery('@mycoll/*').execute().first;
      assertEqual('$first', 'JBDOC: 2 {"foo":"bar"}');

      first = (await db.createQuery('@mycoll/*').first()).orNull;
      assertEqual('$first', 'JBDOC: 2 {"foo":"bar"}');

      first = (await db.createQuery('@mycoll/[zzz=bbb]').first()).orNull;
      assertNull(first);

      list = await db.createQuery('@mycoll/*').firstN(5);
      assertEqual('$list', '[JBDOC: 2 {"foo":"bar"}, JBDOC: 1 {"foo":"baz"}]');

      doc = await db
          .createQuery('@mycoll/[foo=:? and foo=:bar]')
          .setString(0, 'baz')
          .setString('bar', 'baz')
          .execute()
          .first;
      assertEqual('$doc', 'JBDOC: 1 {"foo":"baz"}');

      list = await (db.createQuery('@mycoll/[foo != :?]').setString(0, 'zaz')..skip = 1)
          .execute()
          .toList();
      assertEqual('$list', '[JBDOC: 1 {"foo":"baz"}]');

      error = null;
      try {
        await db['@mycoll/['].execute();
      } catch (e) {
        error = e;
      }
      assertNull(error); // Note: null error

      error = null;
      try {
        await db.createQuery('@mycoll/[').executeTouch();
      } catch (e) {
        error = e;
      }
      assertNotNull(error); // Note: non null error
      assertTrue(error is EJDB2Error);
      assertTrue((error as EJDB2Error).isInvalidQuery());

      final count = await db['@mycoll/* | count'].executeScalarInt();
      assertEqual(count, 2);

      await db.patch('mycoll', '[{"op":"add", "path":"/baz", "value":"qux"}]', 1);
      doc = await db.get('mycoll', 1);
      assertDeepEqual(doc.object, {'foo': 'baz', 'baz': 'qux'});

      var info = await db.info();
      assertEqual(jsonAt(info, '/size').orNull, 8192);
      assertEqual(jsonAt(info, '/collections/0/rnum').orNull, 2);
      assertNull(jsonAt(info, '/collections/0/indexes/0').orNull);

      await db.ensureStringIndex('mycoll', '/foo', true);
      info = await db.info();
      assertEqual(jsonAt(info, '/collections/0/indexes/0/ptr').orNull, '/foo');
      assertEqual(jsonAt(info, '/collections/0/indexes/0/mode').orNull, 5);
      assertEqual(jsonAt(info, '/collections/0/indexes/0/rnum').orNull, 2);

      await db.removeStringIndex('mycoll', '/foo', true);
      info = await db.info();
      assertNull(jsonAt(info, '/collections/0/indexes/0').orNull);

      doc = await db['@mycoll/[foo re :?]'].setRegexp(0, RegExp('.*')).firstRequired();
      assertEqual('$doc', 'JBDOC: 2 {"foo":"bar"}');

      await db.removeCollection('mycoll');
      info = await db.info();
      assertNull(jsonAt(info, '/collections/0').orNull);

      error = null;
      try {
        await db['@mycoll/*'].firstRequired();
      } catch (e) {
        error = e;
      }
      assertNotNull(error); // Note: non null error
      assertTrue(error is EJDB2Error);
      assertTrue((error as EJDB2Error).isNotFound());

      id = await db.put('cc1', {'foo': 1});
      doc = await db.get('cc1', id);
      assertEqual('$doc', 'JBDOC: 1 {"foo":1}');

      await db.renameCollection('cc1', 'cc2');
      doc = await db.get('cc2', id);
      assertEqual('$doc', 'JBDOC: 1 {"foo":1}');

      var opt = await db.getOptional('cc2', id);
      assertTrue(opt.isPresent);

      opt = await db.getOptional('cc2', 122);
      assertTrue(opt.isNotPresent);


      var i = 0;
      for (i = 0; i < 1023; ++i) {
        await db.put('load', {'name': 'v${i}'});
      }

      i = 0;
      await for (final doc in db.createQuery('@load/* | inverse').execute()) {
        final v = doc.object;
        assertEqual(v['name'], 'v${i}');
        ++i;
      }

      dbpath = jsonAt(info, '/file').orNull as String;
      assertNotNull(dbpath);

      final ts0 = DateTime.now().millisecondsSinceEpoch;
      final ts = await db.onlineBackup('${dbpath}.bkp');
      assertTrue(ts0 < ts);

    } catch(e, st) {
      print('$e\n$st');
      rethrow;
    } finally {
      await db.close();
    }

    db = await EJDB2Builder('${dbpath}.bkp').open();
    final doc = await db.get('cc2', 1);
    assertEqual('${doc}', 'JBDOC: 1 {"foo":1}');
    await db.close();
  }

  Future<void> _initTesting() async {
    if (!mounted) return;
    try {
      await _doTest();
      setState(() {
        _result = 'Success';
      });
    } catch (e, s) {
      print('Error $e, $s');
      setState(() {
        _result = 'Fail: ${e}';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: _result == 'Success'
              ? const Text(
                  'Success',
                  key: Key('success'),
                )
              : Text(
                  _result == '' ? '' : 'Fail: ${_result}',
                  key: const Key('fail'),
                ),
        ),
      ),
    );
  }
}

Use this package as a library

1. Depend on it

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


dependencies:
  ejdb2_flutter: ^1.0.17+1

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:ejdb2_flutter/ejdb2_flutter.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
53
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
76
Learn more about scoring.

We analyzed this package on Mar 27, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6
  • Flutter: 1.12.13+hotfix.8

Health suggestions

Format lib/ejdb2_flutter.dart.

Run flutter format to format lib/ejdb2_flutter.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.5.0 <3.0.0
flutter 0.0.0
json_at ^1.0.4 1.0.4
pedantic ^1.8.0+1 1.9.0
quiver ^2.0.5 2.1.3
Transitive dependencies
_fe_analyzer_shared 1.0.3
analyzer 0.39.4
args 1.6.0
async 2.4.1
boolean_selector 2.0.0
charcode 1.1.3
collection 1.14.11 1.14.12
convert 2.1.1
coverage 0.13.9
crypto 2.1.4
csslib 0.16.1
glob 1.2.0
html 0.14.0+3
http 0.12.0+4
http_multi_server 2.2.0
http_parser 3.1.4
io 0.3.3
js 0.6.1+1
logging 0.11.4
matcher 0.12.6
meta 1.1.8
mime 0.9.6+3
multi_server_socket 1.0.2
node_interop 1.0.3
node_io 1.0.1+2
node_preamble 1.4.8
package_config 1.9.3
path 1.6.4
pool 1.4.0
pub_semver 1.4.4
shelf 0.7.5
shelf_packages_handler 2.0.0
shelf_static 0.2.8
shelf_web_socket 0.2.3
sky_engine 0.0.99
source_map_stack_trace 2.0.0
source_maps 0.10.9
source_span 1.7.0
stack_trace 1.9.3
stream_channel 2.0.0
string_scanner 1.0.5
term_glyph 1.1.0
test 1.14.2
test_api 0.2.15
test_core 0.3.3
typed_data 1.1.6
vector_math 2.0.8
vm_service 4.0.0
watcher 0.9.7+14
web_socket_channel 1.1.0
webkit_inspection_protocol 0.5.0+1
yaml 2.2.0
Dev dependencies
flutter_test