Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dart2_3 #47

Merged
merged 5 commits into from
Jan 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion idb_shim/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
## 2.1.1-3
## 2.2.0

* Fix keyPath array index creation
* mimic Chrome and prevent cursor delete when using openKeyCursor
* allow keyPath as List<String> when in createObjectStore.

## 2.1.0

Expand Down
9 changes: 0 additions & 9 deletions idb_shim/analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,6 @@ include: package:lints/recommended.yaml
analyzer:
exclude:
- build/**
strong-mode:
implicit-casts: false
errors:
# treat missing required parameters as a warning (not a hint)
missing_required_param: warning
# treat missing returns as a warning (not a hint)
missing_return: warning
# allow having TODOs in the code
todo: ignore

linter:
rules:
Expand Down
2 changes: 1 addition & 1 deletion idb_shim/lib/idb.dart
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ abstract class Database {
/// This method can be called only within a versionchange transaction.
///
ObjectStore createObjectStore(String name,
{String? keyPath, bool? autoIncrement});
{Object? keyPath, bool? autoIncrement});

///
/// returns a transaction object (Transaction) containing the
Expand Down
16 changes: 12 additions & 4 deletions idb_shim/lib/src/common/common_meta.dart
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ abstract class ObjectStoreWithMetaMixin {
IdbObjectStoreMeta? get meta;

//@override
String? get keyPath => meta!.keyPath;
Object? get keyPath => meta!.keyPath;

//@override
bool get autoIncrement => meta!.autoIncrement;
Expand All @@ -228,7 +228,7 @@ class IdbObjectStoreMeta {
static const String indeciesKey = 'indecies';

final String name;
final String? keyPath;
final Object? keyPath;
final bool autoIncrement;

Iterable<IdbIndexMeta> get indecies => _indecies.values;
Expand Down Expand Up @@ -291,11 +291,19 @@ class IdbObjectStoreMeta {
}
}

static Object? _keyPathAsStringOrList(Object? keyPath) {
if (keyPath is Iterable) {
return keyPath.cast<String>().toList();
} else {
return keyPath?.toString();
}
}

IdbObjectStoreMeta.fromMap(Map<String, Object?> map) //
: this(
//
map[nameKey] as String, //
map[keyPathKey] as String?, //
_keyPathAsStringOrList(map[keyPathKey]),
map[autoIncrementKey] as bool?,
IdbIndexMeta.fromMapList(
((map[indeciesKey]) as List?)?.cast<Map>()));
Expand Down Expand Up @@ -431,7 +439,7 @@ abstract class IndexWithMetaMixin {

class IdbIndexMeta {
final String? name;
final dynamic keyPath;
final Object? keyPath;
final bool unique;
final bool multiEntry;

Expand Down
8 changes: 7 additions & 1 deletion idb_shim/lib/src/common/common_validation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ void checkKeyParam(var key) {
}
}

/// Check a key
void checkKeyValueParam(
{String? keyPath, dynamic key, dynamic value, bool? autoIncrement}) {
{
/** List<String> | String */
Object? keyPath,
dynamic key,
dynamic value,
bool? autoIncrement}) {
if (key != null) {
checkKeyParam(key);
if (keyPath != null) {
Expand Down
85 changes: 80 additions & 5 deletions idb_shim/lib/src/common/common_value.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ library idb_shim_common_value;
import 'dart:convert';

import 'package:idb_shim/idb.dart';
import 'package:idb_shim/src/utils/env_utils.dart';

/// encode a value using JSON.
dynamic encodeValue(dynamic value) {
Expand Down Expand Up @@ -117,13 +118,20 @@ KeyRange keyArrayRangeAt(KeyRange keyRange, int index) {
}

/// return a list if keyPath is an array
Object? mapValueAtKeyPath(Map? map, keyPath) {
///
/// if [keyPath] is a, the list cannot contain null values and null is returned instead.
Object? mapValueAtKeyPath(Map? map, Object? keyPath) {
if (keyPath is String) {
return getMapFieldValue(map, keyPath);
} else if (keyPath is List) {
final keyList = keyPath;
return List.generate(
var keys = List.generate(
keyList.length, (i) => getMapFieldValue(map, keyPath[i] as String));
if (keys.where((element) => element == null).isNotEmpty) {
/// the list cannot contain null values
return null;
}
return keys;
}
throw 'keyPath $keyPath not supported';
}
Expand Down Expand Up @@ -180,12 +188,12 @@ T? getPartsMapValue<T>(Map? map, Iterable<String> parts) {
}

/// Set a field value.
void setMapFieldValue<T>(Map map, String field, T value) {
void setMapFieldValue(Map map, String field, Object value) {
setPartsMapValue(map, getFieldParts(field), value);
}

/// Set a a deep map member value
void setPartsMapValue<T>(Map map, List<String> parts, value) {
void setPartsMapValue(Map map, List<String> parts, Object value) {
for (var i = 0; i < parts.length - 1; i++) {
final part = parts[i];
dynamic sub = map[part];
Expand All @@ -195,5 +203,72 @@ void setPartsMapValue<T>(Map map, List<String> parts, value) {
}
map = sub;
}
map[parts.last] = value;
var key = parts.last;
map[key] = value;
}

/// Common extension
extension IdbValueMapExt on Map {
/// return a list if keyPath is an array
///
/// if [keyPath] is a, the list cannot contain null values and null is returned instead.
Object? getKeyValue(Object? keyPath) {
if (keyPath is String) {
return getFieldValue(keyPath);
} else if (keyPath is List) {
final keyList = keyPath;
var keys = List.generate(
keyList.length, (i) => getFieldValue(keyPath[i] as String));
if (keys.where((element) => element == null).isNotEmpty) {
/// the list cannot contain null values
return null;
}
return keys;
}
throw 'keyPath $keyPath not supported';
}

/// return a list if keyPath is an array
///
/// if [keyPath] is a, the list cannot contain null values and null is returned instead.
void setKeyValue(Object? keyPath, Object value) {
if (keyPath is String) {
return setFieldValue(keyPath, value);
} else if (keyPath is List) {
final keyList = keyPath;
if (isDebug) {
if (value is! List) {
throw ArgumentError.value(value, 'key value', 'is not a list');
}
if (keyPath is! List<String>) {
throw ArgumentError.value(
keyPath, 'keyPath', 'is not a list of string');
}
if (value.length != keyList.length) {
throw ArgumentError.value('$keyPath: $value', 'keyPath: value',
'length do not match (${keyList.length} vs ${value.length}');
}
}

/// value must be a list

final valueList = value as List<Object?>;
assert(keyList.length == valueList.length);
for (var i = 0; i < keyList.length; i++) {
setFieldValue(keyList[i], valueList[i]!);
}
} else {
throw 'keyPath $keyPath not supported';
}
}

/// Get map field helper.
T? getFieldValue<T>(String field) {
return getPartsMapValue(this, getFieldParts(field));
}

/// Set a field value.
void setFieldValue(String field, Object value) {
setPartsMapValue(this, getFieldParts(field), value);
}
}
2 changes: 1 addition & 1 deletion idb_shim/lib/src/logger/logger_database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class DatabaseLogger extends IdbDatabaseBase {

@override
ObjectStore createObjectStore(String name,
{String? keyPath, bool? autoIncrement}) {
{Object? keyPath, bool? autoIncrement}) {
log('createObjectStore($name${getPropertyMapText({
'keyPath': keyPath,
'autoIncrement': autoIncrement
Expand Down
2 changes: 1 addition & 1 deletion idb_shim/lib/src/native/native_database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class DatabaseNative extends IdbDatabaseBase {

@override
ObjectStore createObjectStore(String name,
{String? keyPath, bool? autoIncrement}) {
{Object? keyPath, bool? autoIncrement}) {
return catchNativeError(() {
return ObjectStoreNative(idbDatabase!.createObjectStore(name,
keyPath: keyPath, autoIncrement: autoIncrement));
Expand Down
2 changes: 1 addition & 1 deletion idb_shim/lib/src/sembast/sembast_database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ class DatabaseSembast extends IdbDatabaseBase with DatabaseWithMetaMixin {

@override
ObjectStore createObjectStore(String name,
{String? keyPath, bool? autoIncrement}) {
{Object? keyPath, bool? autoIncrement}) {
final storeMeta = IdbObjectStoreMeta(name, keyPath, autoIncrement);
meta.createObjectStore(storeMeta);
return ObjectStoreSembast(versionChangeTransaction, storeMeta);
Expand Down
2 changes: 1 addition & 1 deletion idb_shim/lib/src/sembast/sembast_object_store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class ObjectStoreSembast extends ObjectStore with ObjectStoreWithMetaMixin {
/// Need for add without explicit key
Object fixKeyInValueImpl(Object value, Object key) {
if ((keyPath != null) && (value is Map)) {
return cloneValue(value, keyPath, key);
return cloneValue(value, keyPath as String, key);
}
return value;
}
Expand Down
17 changes: 17 additions & 0 deletions idb_shim/lib/src/utils/env_utils.dart
Original file line number Diff line number Diff line change
@@ -1,2 +1,19 @@
/// Special runtime trick to known whether we are in the javascript world
const idbIsRunningAsJavascript = identical(0, 0.0);

bool? _isRelease;

/// Check whether in release mode
bool? get isRelease {
if (_isRelease == null) {
_isRelease = true;
assert(() {
_isRelease = false;
return true;
}());
}
return _isRelease;
}

/// Check whether running in debug mode
bool get isDebug => !isRelease!;
2 changes: 1 addition & 1 deletion idb_shim/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: idb_shim
version: 2.1.1-3
version: 2.2.0
description: indexed_db dart base interface with implementation for native (browser), file (io) and in memory.
homepage: https://github.com/tekartik/idb_shim.dart/tree/master/idb_shim

Expand Down
28 changes: 20 additions & 8 deletions idb_shim/test/multiplatform/common_meta_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ final IdbObjectStoreMeta idbObjectStoreMeta3 =
IdbObjectStoreMeta('name', null, true);
final IdbObjectStoreMeta idbObjectStoreMeta4 =
IdbObjectStoreMeta('other_name', 'my_key', true);
final IdbObjectStoreMeta idbObjectStoreMetaComposite =
IdbObjectStoreMeta('composite', ['my', 'key'], false);
final List<IdbObjectStoreMeta> idbObjectStoreMetas = [
idbObjectStoreMeta1,
idbObjectStoreMeta2,
idbObjectStoreMeta3
idbObjectStoreMeta3,
];

IdbIndexMeta idbIndexMeta1 = IdbIndexMeta('name', 'my_key', true, true);
Expand Down Expand Up @@ -55,11 +57,18 @@ void defineTests() {
expect(meta1, isNot(meta3));
});

void testStoreRoundTrip(IdbObjectStoreMeta meta) {
var map = meta.toMap();
final newMeta = IdbObjectStoreMeta.fromMap(map);
expect(newMeta, meta);
}

test('store', () {
expect(idbObjectStoreMeta1, idbObjectStoreMeta1Same);
expect(idbObjectStoreMeta1, isNot(idbObjectStoreMeta2));
expect(idbObjectStoreMeta1, isNot(idbObjectStoreMeta3));
expect(idbObjectStoreMeta1, isNot(idbObjectStoreMeta4));
testStoreRoundTrip(idbObjectStoreMeta1);
});

test('index', () {
Expand All @@ -79,8 +88,17 @@ void defineTests() {
final meta3 = idbSimpleObjectStoreMeta.clone();
meta2.putIndex(idbIndexMeta2);
expect(meta1, isNot(meta3));
testStoreRoundTrip(meta1);
});

test('store with keyPath array', () {
final meta = idbObjectStoreMetaComposite;
expect(meta.toMap(), {
'name': 'composite',
'keyPath': ['my', 'key']
});
testStoreRoundTrip(meta);
});
test('store with three indecies', () {
final meta = idbSimpleObjectStoreMeta.clone();
meta.putIndex(IdbIndexMeta('index3', 'keyA', true, false));
Expand All @@ -102,13 +120,7 @@ void defineTests() {
});
});

void testStoreRoundTrip(IdbObjectStoreMeta meta) {
var map = meta.toMap();
final newMeta = IdbObjectStoreMeta.fromMap(map);
expect(newMeta, meta);
}

test('store with keyPath array', () {
test('store with keyPath array index', () {
final meta = idbSimpleObjectStoreMeta.clone();
meta.putIndex(IdbIndexMeta('index3', ['keyA', 'keyB'], true, false));
expect(meta.toMap(), {
Expand Down
11 changes: 10 additions & 1 deletion idb_shim/test/multiplatform/common_validation_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ void defineTests() {
});

void checkKeyValueParamFail(
{String? keyPath, dynamic key, dynamic value, bool? autoIncrement}) {
{Object? keyPath, dynamic key, dynamic value, bool? autoIncrement}) {
try {
checkKeyValueParam(
keyPath: keyPath,
Expand All @@ -44,6 +44,15 @@ void defineTests() {
fail('$key should fail');
}

test('composite checkKeyValueParam', () {
// DataError: neither keyPath nor autoIncrement set and trying to add object without key.
checkKeyValueParamFail(keyPath: ['my', 'key']);
checkKeyValueParamFail(
keyPath: ['my', 'key'], value: {'my': 1, 'key': null});
checkKeyValueParamFail(keyPath: ['my', 'key'], value: {'my': 1});
checkKeyValueParam(
keyPath: ['my', 'key'], value: {'my': 1, 'key': 'text'});
});
test('checkKeyValueParam', () {
checkKeyValueParamFail(keyPath: 'keyPath', key: 'key', value: {});
checkKeyValueParamFail(
Expand Down
19 changes: 19 additions & 0 deletions idb_shim/test/multiplatform/common_value_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,24 @@ void defineTests() {
expect(keyRange.lower, null);
expect(keyRange.upper, 'John');
});

test('IdbValueMapExt', () {
var map = <String, Object?>{'key': 1};
expect(map.getFieldValue('key'), 1);
expect(map.getKeyValue('key'), 1);
expect(map.getKeyValue(['key']), [1]);
map.setKeyValue('key', 2);
expect(map.getKeyValue(['key']), [2]);
map.setKeyValue(['key'], [3]);
expect(map.getKeyValue('key'), 3);
expect(map, {'key': 3});
map.setKeyValue('my', 'text');
expect(map, {'key': 3, 'my': 'text'});
map.setKeyValue(['my', 'key'], [4, 'text']);
expect(map.getKeyValue(['my', 'key']), [4, 'text']);
expect(map, {'key': 'text', 'my': 4});
map.setFieldValue('my', 1);
expect(map, {'key': 'text', 'my': 1});
});
});
}
Loading