diff --git a/docker/README.md b/docker/README.md index 52012f4e..58a8694e 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,11 +1,24 @@ -# Working with Docker +# Docker setup -## Postgresql +## PostreSQL -### Starting the container +### Starting the PostreSQL container ```bash - docker-compose -f docker-compose-pg.yml up + docker compose -f docker-compose-pg.yml up -d + ``` + +### Stopping the PostreSQL container + + ```bash + docker compose -f docker-compose-pg.yml stop + docker compose -f docker-compose-pg.yml down + ``` + +### Checking the PostreSQL container log + + ```bash + docker logs docker-pg-1 -f ``` ### Running psql @@ -25,6 +38,84 @@ ## MariaDB +### Starting the MariaDB container + + ```bash + docker compose -f docker-compose-mariadb.yml up -d + ``` + +### Stopping the MariaDB container + + ```bash + docker compose -f docker-compose-mariadb.yml stop + docker compose -f docker-compose-mariadb.yml down + ``` + +### Checking the MariaDB container log + + ```bash + docker logs docker-mariadb-1 -f + ``` + ## MySQL +### Starting the MySQL container + + ```bash + docker compose -f docker-compose-mysql.yml up -d + ``` + +### Stopping the MySQL container + + ```bash + docker compose -f docker-compose-mysql.yml stop + docker compose -f docker-compose-mysql.yml down + ``` + +### Checking the MySQL container log + + ```bash + docker logs docker-mysql-1 -f + ``` + +## MongoDB + +### Starting the MongoDB container + + ```bash + docker compose -f docker-compose-mongo.yml up -d + ``` + +### Stopping the MongoDB container + + ```bash + docker compose -f docker-compose-mongo.yml stop + docker compose -f docker-compose-mongo.yml down + ``` + +### Checking the MongoDB container log + + ```bash + docker logs docker-mongo-1 -f + ``` + ## Redis + +### Starting the Redis container + + ```bash + docker compose -f docker-compose-redis.yml up -d + ``` + +### Stopping the Redis container + + ```bash + docker compose -f docker-compose-redis.yml stop + docker compose -f docker-compose-redis.yml down + ``` + +### Checking the Redis container log + + ```bash + docker logs docker-redis-1 -f + ``` diff --git a/docker/docker-compose-mariadb.yml b/docker/docker-compose-mariadb.yml index 91a71473..e7c9a473 100644 --- a/docker/docker-compose-mariadb.yml +++ b/docker/docker-compose-mariadb.yml @@ -1,4 +1,3 @@ -version: "3.8" services: mariadb: image: mariadb:latest diff --git a/docker/docker-compose-mongo.yml b/docker/docker-compose-mongo.yml new file mode 100644 index 00000000..e27d0cb7 --- /dev/null +++ b/docker/docker-compose-mongo.yml @@ -0,0 +1,38 @@ +services: + + mongo: + image: mongo + restart: no + ports: + - 27017:27017 + environment: + #MONGO_INITDB_ROOT_USERNAME: root + #MONGO_INITDB_ROOT_PASSWORD: example + MONGO_INITDB_DATABASE: local + volumes: + - "mongo:/data/db" + networks: + - webnet + + mongo-express: + image: mongo-express + restart: no + depends_on: + - mongo + ports: + - 8081:8081 + environment: + #ME_CONFIG_MONGODB_ADMINUSERNAME: root + #ME_CONFIG_MONGODB_ADMINPASSWORD: example + #ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/ + ME_CONFIG_MONGODB_URL: mongodb://mongo:27017/ + ME_CONFIG_BASICAUTH: false + networks: + - webnet + +volumes: + mongo: + driver: local + +networks: + webnet: diff --git a/docker/docker-compose-mysql.yml b/docker/docker-compose-mysql.yml index 14e64ef9..6d9fe5c0 100644 --- a/docker/docker-compose-mysql.yml +++ b/docker/docker-compose-mysql.yml @@ -1,4 +1,3 @@ -version: "3.8" services: mysql: image: mysql:latest diff --git a/docker/docker-compose-pg.yml b/docker/docker-compose-pg.yml index f6c1b4e7..cdd19d35 100644 --- a/docker/docker-compose-pg.yml +++ b/docker/docker-compose-pg.yml @@ -1,4 +1,3 @@ -version: "3.8" services: pgdb: image: postgres:latest diff --git a/docker/docker-compose-redis.yml b/docker/docker-compose-redis.yml index b39a2d68..59cb46b4 100644 --- a/docker/docker-compose-redis.yml +++ b/docker/docker-compose-redis.yml @@ -1,4 +1,3 @@ -version: "3.8" services: redis: image: redis:latest diff --git a/packages/jael/jael_web/CHANGELOG.md b/packages/jael/jael_web/CHANGELOG.md index 00e4635a..88a33592 100644 --- a/packages/jael/jael_web/CHANGELOG.md +++ b/packages/jael/jael_web/CHANGELOG.md @@ -1,21 +1,12 @@ # Change Log -## 8.2.1 - -* Updated repository link - -## 8.2.0 - -* Updated `lints` to 3.0.0 -* Fixed linter warnings - -## 8.1.0 - -* Upgraded to `analyzer` 6.2.x - ## 8.0.0 -* Require Dart >= 3.0 +* Require Dart >= 3.3 +* Updated `lints` to 3.0.0 +* Updated `analyzer` to 6.2.x +* Fixed linter warnings +* Updated repository link ## 7.1.1 diff --git a/packages/jael/jael_web/README.md b/packages/jael/jael_web/README.md index 8f812076..fc85bf5e 100644 --- a/packages/jael/jael_web/README.md +++ b/packages/jael/jael_web/README.md @@ -8,4 +8,4 @@ Experimental virtual DOM/SPA engine built on Jael. Supports SSR. ## TODO -* Builder failed to generate the class +* Bug: Builder failed to generate the class diff --git a/packages/jael/jael_web/lib/src/builder/util.dart b/packages/jael/jael_web/lib/src/builder/util.dart index 3518221f..d0a38b2c 100644 --- a/packages/jael/jael_web/lib/src/builder/util.dart +++ b/packages/jael/jael_web/lib/src/builder/util.dart @@ -12,7 +12,7 @@ import 'package:path/path.dart'; /// Converts a [DartType] to a [TypeReference]. TypeReference convertTypeReference(DartType? t) { return TypeReference((b) { - b.symbol = t?.getDisplayString(withNullability: false); + b.symbol = t?.getDisplayString(); if (t is InterfaceType) { b.types.addAll(t.typeArguments.map(convertTypeReference)); diff --git a/packages/jael/jael_web/lib/src/jael_component.dart b/packages/jael/jael_web/lib/src/jael_component.dart index 702b81ec..e7bf67a8 100644 --- a/packages/jael/jael_web/lib/src/jael_component.dart +++ b/packages/jael/jael_web/lib/src/jael_component.dart @@ -14,6 +14,5 @@ class Jael { /// Shorthand for enabling `DSX` syntax when using a [Jael] annotation. class Dsx extends Jael { - const Dsx({String? template, String? templateUrl}) - : super(template: template, templateUrl: templateUrl, asDsx: true); + const Dsx({super.template, super.templateUrl}) : super(asDsx: true); } diff --git a/packages/jael/jael_web/pubspec.yaml b/packages/jael/jael_web/pubspec.yaml index 941a6297..0e3ff535 100644 --- a/packages/jael/jael_web/pubspec.yaml +++ b/packages/jael/jael_web/pubspec.yaml @@ -1,5 +1,5 @@ name: jael3_web -version: 8.2.0 +version: 8.0.0 description: Experimental virtual DOM/SPA engine built on Jael3. Supports SSR. publish_to: none environment: diff --git a/packages/model/CHANGELOG.md b/packages/model/CHANGELOG.md index 86374d8d..84cf9dde 100644 --- a/packages/model/CHANGELOG.md +++ b/packages/model/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 8.2.0 + +* Require Dart >= 3.3 +* Updated `lints` to 4.0.0 + ## 8.1.1 * Updated repository link diff --git a/packages/model/pubspec.yaml b/packages/model/pubspec.yaml index eae6093d..4a02e141 100644 --- a/packages/model/pubspec.yaml +++ b/packages/model/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_model -version: 8.1.1 +version: 8.2.0 description: Angel3 basic data model class, no longer with the added weight of the whole framework. homepage: https://angel3-framework.web.app/ repository: https://github.com/dart-backend/angel/tree/master/packages/model diff --git a/packages/mongo/CHANGELOG.md b/packages/mongo/CHANGELOG.md index a544d8f1..93f4f4ee 100644 --- a/packages/mongo/CHANGELOG.md +++ b/packages/mongo/CHANGELOG.md @@ -3,9 +3,10 @@ ## 8.2.0 * Require Dart >= 3.3 -* Updated `mongo_dart` to 0.10.2 -* Updated `lints` to 3.0.0 -* Fixed deprecated methods +* Updated `mongo_dart` to 0.10.3 +* Updated `lints` to 4.0.0 +* Refactored `mongo_service` class +* Refactored test cases ## 8.1.1 diff --git a/packages/mongo/README.md b/packages/mongo/README.md index 31469b92..b797db68 100644 --- a/packages/mongo/README.md +++ b/packages/mongo/README.md @@ -44,7 +44,7 @@ void main() async { ## MongoService -This class interacts with a `DbCollection` (from mongo_dart) and serializing data to and from Maps. +This class interacts with `DbCollection` (from mongo_dart) and serializing data to and from Maps. ## Querying @@ -57,9 +57,20 @@ You can query these services as follows: The above will query the database to find records where 'foo' equals 'bar'. The former will sort result in ascending order of creation, and so will the latter. ```dart - List queried = await MyService.index({r"$query": where.id(new ObjectId.fromHexString("some hex string"}))); + List queried = await MyService.index({r"$query": where.id(ObjectId.fromHexString("some hex string"}))); ``` -And, of course, you can use mongo_dart queries. Just pass it as `query` within `params`. +And, you can use mongo_dart queries. Just pass it as `query` within `params`. See the tests for more usage examples. + +## **Important Notes** + +When running with locally installed instance of MongoDB or docker based MongoDB, the following connection string is not supported by the underlying MongoDB driver yet. Best option at the moment is to run MongoDB with the authentication off or use MongoDB Atlas. + +```dart + var db = Db('mongodb://:@localhost:27017/local'); +``` + +* `` is MongoDB username +* `` is MongoDB password diff --git a/packages/mongo/example/example.dart b/packages/mongo/example/example.dart index e888c666..9618969b 100644 --- a/packages/mongo/example/example.dart +++ b/packages/mongo/example/example.dart @@ -1,10 +1,11 @@ +import 'package:angel3_container/mirrors.dart'; import 'package:angel3_framework/angel3_framework.dart'; import 'package:angel3_mongo/angel3_mongo.dart'; import 'package:mongo_dart/mongo_dart.dart'; void main() async { - var app = Angel(); - var db = Db('mongodb://localhost:27017/local'); + var app = Angel(reflector: MirrorsReflector()); + var db = Db('mongodb://root:example@localhost:27017/local'); await db.open(); var service = app.use('/api/users', MongoService(db.collection('users'))); diff --git a/packages/mongo/lib/mongo_service.dart b/packages/mongo/lib/mongo_service.dart index dc3cd784..86fd3900 100644 --- a/packages/mongo/lib/mongo_service.dart +++ b/packages/mongo/lib/mongo_service.dart @@ -90,7 +90,8 @@ class MongoService extends Service> { .toList(); } - static const String _nonceKey = '__angel__mongo__nonce__key__'; + // Deprecated: + //static const String _nonceKey = '__angel__mongo__nonce__key__'; @override Future> create(Map data, @@ -98,13 +99,19 @@ class MongoService extends Service> { var item = _removeSensitive(data); try { - var nonce = (await collection.db.getNonce())['nonce'] as String?; - var result = await (collection.findAndModify( - query: where.eq(_nonceKey, nonce), - update: item, - returnNew: true, - upsert: true) as FutureOr>); - return _jsonify(result); + if (params == null || params.isEmpty) { + var result = await collection.insertOne(data); + return _jsonify(result.document ?? {}); + } else { + // Deprecated: + // var nonce = (await collection.db.getNonce())['nonce'] as String?; + var result = await collection.findAndModify( + query: _makeQuery(params), + update: item, + returnNew: true, + upsert: true); + return _jsonify(result ?? {}); + } } catch (e, st) { throw AngelHttpException(stackTrace: st); } @@ -150,10 +157,10 @@ class MongoService extends Service> { @override Future> modify(String id, data, [Map? params]) async { - Map target; + Map currentDoc; try { - target = await read(id, params); + currentDoc = await read(id, params); } on AngelHttpException catch (e) { if (e.statusCode == 404) { return await create(data, params); @@ -162,15 +169,13 @@ class MongoService extends Service> { } } - var result = mergeMap([target, _removeSensitive(data)]); - //result['updatedAt'] = new DateTime.now().toIso8601String(); + var updatedDoc = mergeMap([currentDoc, _removeSensitive(data)]); + updatedDoc['updatedAt'] = DateTime.now().toIso8601String(); try { - var modified = await (collection.findAndModify( - query: where.id(_makeId(id)), - update: result, - returnNew: true) as FutureOr>); - result = _jsonify(modified, params); + var modified = await collection.findAndModify( + query: where.id(_makeId(id)), update: updatedDoc, returnNew: true); + var result = _jsonify(modified ?? {}, params); result['id'] = _makeId(id).oid; return result; } catch (e, st) { @@ -182,23 +187,17 @@ class MongoService extends Service> { @override Future> update(String id, Map data, [Map? params]) async { - var result = _removeSensitive(data); - result['_id'] = _makeId(id); - /*result['createdAt'] = - target is Map ? target['createdAt'] : target.createdAt; + var updatedDoc = _removeSensitive(data); - if (result['createdAt'] is DateTime) - result['createdAt'] = result['createdAt'].toIso8601String(); - - result['updatedAt'] = new DateTime.now().toIso8601String();*/ + updatedDoc['updatedAt'] = DateTime.now().toIso8601String(); try { - var updated = await (collection.findAndModify( + var updated = await collection.findAndModify( query: where.id(_makeId(id)), - update: result, + update: updatedDoc, returnNew: true, - upsert: true) as FutureOr>); - result = _jsonify(updated, params); + upsert: true); + var result = _jsonify(updated ?? {}, params); result['id'] = _makeId(id).oid; return result; } catch (e, st) { @@ -225,10 +224,9 @@ class MongoService extends Service> { // var result = await read(id, params); try { - var result = await (collection.findAndModify( - query: where.id(_makeId(id)), - remove: true) as FutureOr>); - return _jsonify(result); + var result = await collection.findAndModify( + query: where.id(_makeId(id)), remove: true); + return _jsonify(result ?? {}); } catch (e, st) { //printDebug(e, st, 'REMOVE'); throw AngelHttpException(stackTrace: st); diff --git a/packages/mongo/pubspec.yaml b/packages/mongo/pubspec.yaml index 1910ff45..5b3a066a 100644 --- a/packages/mongo/pubspec.yaml +++ b/packages/mongo/pubspec.yaml @@ -7,9 +7,10 @@ environment: sdk: '>=3.3.0 <4.0.0' dependencies: angel3_framework: ^8.0.0 + angel3_container: ^8.0.0 belatuk_json_serializer: ^7.1.0 belatuk_merge_map: ^5.1.0 - mongo_dart: ^0.10.2 + mongo_dart: ^0.10.3 dev_dependencies: http: ^1.0.0 test: ^1.24.0 diff --git a/packages/mongo/test/generic_test.dart b/packages/mongo/test/generic_test.dart index be8c11fb..961acc2b 100644 --- a/packages/mongo/test/generic_test.dart +++ b/packages/mongo/test/generic_test.dart @@ -1,3 +1,4 @@ +import 'package:angel3_container/mirrors.dart'; import 'package:angel3_framework/angel3_framework.dart'; import 'package:angel3_framework/http.dart'; import 'package:angel3_mongo/angel3_mongo.dart'; @@ -25,18 +26,19 @@ void main() { Angel app; late AngelHttp transport; late http.Client client; - var db = Db('mongodb://localhost:27017/angel_mongo'); + var db = Db('mongodb://localhost:27017/testingDB'); + late DbCollection testData; String? url; late HookedService, MongoService> greetingService; setUp(() async { - app = Angel(); + app = Angel(reflector: MirrorsReflector()); transport = AngelHttp(app); client = http.Client(); await db.open(); - testData = db.collection('test_data'); + testData = db.collection('testData'); // Delete anything before we start await testData.remove({}); @@ -126,30 +128,30 @@ void main() { var response = await client.post(Uri.parse('$url/api'), body: god.serialize(testGreeting), headers: headers); expect(response.statusCode, isIn([200, 201])); - var created = god.deserialize(response.body) as Map; + var createdDoc = god.deserialize(response.body) as Map; - response = await client.patch(Uri.parse("$url/api/${created['id']}"), + response = await client.patch(Uri.parse("$url/api/${createdDoc['id']}"), body: god.serialize({'to': 'Mom'}), headers: headers); - var modified = god.deserialize(response.body) as Map; + var modifiedDoc = god.deserialize(response.body) as Map; expect(response.statusCode, isIn([200, 201])); - expect(modified['id'], equals(created['id'])); - expect(modified['to'], equals('Mom')); - //expect(modified['updatedAt'], isNot(null)); + expect(modifiedDoc['id'], equals(createdDoc['id'])); + expect(modifiedDoc['to'], equals('Mom')); + expect(modifiedDoc['updatedAt'], isNot(null)); }); test('update item', () async { var response = await client.post(Uri.parse('$url/api'), body: god.serialize(testGreeting), headers: headers); expect(response.statusCode, isIn([200, 201])); - var created = god.deserialize(response.body) as Map; + var createdDoc = god.deserialize(response.body) as Map; - response = await client.post(Uri.parse("$url/api/${created['id']}"), + response = await client.post(Uri.parse("$url/api/${createdDoc['id']}"), body: god.serialize({'to': 'Updated'}), headers: headers); - var modified = god.deserialize(response.body) as Map; + var modifiedDoc = god.deserialize(response.body) as Map; expect(response.statusCode, isIn([200, 201])); - expect(modified['id'], equals(created['id'])); - expect(modified['to'], equals('Updated')); - //expect(modified['updatedAt'], isNot(null)); + expect(modifiedDoc['id'], equals(createdDoc['id'])); + expect(modifiedDoc['to'], equals('Updated')); + expect(modifiedDoc['updatedAt'], isNot(null)); }); test('remove item', () async { diff --git a/packages/serialize/angel_serialize_generator/lib/angel3_serialize_generator.dart b/packages/serialize/angel_serialize_generator/lib/angel3_serialize_generator.dart index d9914a5b..7dddddee 100644 --- a/packages/serialize/angel_serialize_generator/lib/angel3_serialize_generator.dart +++ b/packages/serialize/angel_serialize_generator/lib/angel3_serialize_generator.dart @@ -100,7 +100,7 @@ String? dartObjectToString(DartObject v) { return '#${v.toSymbolValue()!}'; } if (v.toTypeValue() != null) { - return v.toTypeValue()!.getDisplayString(withNullability: true); + return v.toTypeValue()!.getDisplayString(); } if (v.toListValue() != null) { return 'const [${v.toListValue()!.map(dartObjectToString).join(', ')}]'; diff --git a/packages/serialize/angel_serialize_generator/lib/serialize.dart b/packages/serialize/angel_serialize_generator/lib/serialize.dart index f7fa2328..5812d4a8 100644 --- a/packages/serialize/angel_serialize_generator/lib/serialize.dart +++ b/packages/serialize/angel_serialize_generator/lib/serialize.dart @@ -189,12 +189,11 @@ class ${pascal}Decoder extends Converter { // Serialize model classes via `XSerializer.toMap` else if (isModelClass(type)) { - var rc = ReCase(type.getDisplayString(withNullability: true)); + var rc = ReCase(type.getDisplayString()); serializedRepresentation = serializerToMap(rc, 'model.${field.name}'); } else if (type is InterfaceType) { if (isListOfModelType(type)) { - var name = - type.typeArguments[0].getDisplayString(withNullability: true); + var name = type.typeArguments[0].getDisplayString(); if (name.startsWith('_')) name = name.substring(1); var rc = ReCase(name); var m = serializerToMap(rc, 'm'); @@ -207,8 +206,7 @@ class ${pascal}Decoder extends Converter { 'model.${field.name}$question.map((m) => $m).toList()'; log.fine('serializedRepresentation => $serializedRepresentation'); } else if (isMapToModelType(type)) { - var rc = ReCase( - type.typeArguments[1].getDisplayString(withNullability: true)); + var rc = ReCase(type.typeArguments[1].getDisplayString()); serializedRepresentation = '''model.${field.name}.keys.fold({}, (map, key) { return map..[key] = @@ -222,7 +220,7 @@ class ${pascal}Decoder extends Converter { serializedRepresentation = ''' model.${field.name} != null ? - ${type.getDisplayString(withNullability: false)}.values.indexOf(model.${field.name}$convert) + ${type.getDisplayString()}.values.indexOf(model.${field.name}$convert) : null '''; } else if (const TypeChecker.fromRuntime(Uint8List) @@ -357,7 +355,7 @@ class ${pascal}Decoder extends Converter { // Serialize model classes via `XSerializer.toMap` else if (isModelClass(type)) { - var rc = ReCase(type.getDisplayString(withNullability: true)); + var rc = ReCase(type.getDisplayString()); deserializedRepresentation = "map['$alias'] != null" " ? ${rc.pascalCase.replaceAll('?', '')}Serializer.fromMap(map['$alias'] as Map)" ' : $defaultValue'; @@ -366,8 +364,7 @@ class ${pascal}Decoder extends Converter { if (defaultValue == 'null') { defaultValue = '[]'; } - var rc = ReCase( - type.typeArguments[0].getDisplayString(withNullability: true)); + var rc = ReCase(type.typeArguments[0].getDisplayString()); deserializedRepresentation = "map['$alias'] is Iterable" " ? List.unmodifiable(((map['$alias'] as Iterable)" @@ -380,8 +377,7 @@ class ${pascal}Decoder extends Converter { defaultValue = '{}'; } - var rc = ReCase( - type.typeArguments[1].getDisplayString(withNullability: true)); + var rc = ReCase(type.typeArguments[1].getDisplayString()); deserializedRepresentation = ''' map['$alias'] is Map ? Map.unmodifiable((map['$alias'] as Map).keys.fold({}, (out, key) { @@ -392,12 +388,12 @@ class ${pascal}Decoder extends Converter { '''; } else if (type.element is Enum) { deserializedRepresentation = ''' - map['$alias'] is ${type.getDisplayString(withNullability: true)} - ? (map['$alias'] as ${type.getDisplayString(withNullability: true)}) ?? $defaultValue + map['$alias'] is ${type.getDisplayString()} + ? (map['$alias'] as ${type.getDisplayString()}) ?? $defaultValue : ( map['$alias'] is int - ? ${type.getDisplayString(withNullability: true)}.values[map['$alias'] as int] + ? ${type.getDisplayString()}.values[map['$alias'] as int] : $defaultValue ) ''';