Merge pull request #128 from dukefirehawk/feature/upgrade_sdk

Feature/upgrade sdk
This commit is contained in:
Thomas 2024-06-23 11:24:24 +08:00 committed by GitHub
commit 3c6d2c2e87
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 230 additions and 100 deletions

View file

@ -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
```

View file

@ -1,4 +1,3 @@
version: "3.8"
services:
mariadb:
image: mariadb:latest

View file

@ -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:

View file

@ -1,4 +1,3 @@
version: "3.8"
services:
mysql:
image: mysql:latest

View file

@ -1,4 +1,3 @@
version: "3.8"
services:
pgdb:
image: postgres:latest

View file

@ -1,4 +1,3 @@
version: "3.8"
services:
redis:
image: redis:latest

View file

@ -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

View file

@ -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

View file

@ -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));

View file

@ -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);
}

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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://<username>:<password>@localhost:27017/local');
```
* `<username>` is MongoDB username
* `<password>` is MongoDB password

View file

@ -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')));

View file

@ -90,7 +90,8 @@ class MongoService extends Service<String, Map<String, dynamic>> {
.toList();
}
static const String _nonceKey = '__angel__mongo__nonce__key__';
// Deprecated:
//static const String _nonceKey = '__angel__mongo__nonce__key__';
@override
Future<Map<String, dynamic>> create(Map<String, dynamic> data,
@ -98,13 +99,19 @@ class MongoService extends Service<String, Map<String, dynamic>> {
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<Map<String, dynamic>>);
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<String, Map<String, dynamic>> {
@override
Future<Map<String, dynamic>> modify(String id, data,
[Map<String, dynamic>? params]) async {
Map<String, dynamic> target;
Map<String, dynamic> 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<String, Map<String, dynamic>> {
}
}
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<Map<String, dynamic>>);
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<String, Map<String, dynamic>> {
@override
Future<Map<String, dynamic>> update(String id, Map<String, dynamic> data,
[Map<String, dynamic>? 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<Map<String, dynamic>>);
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<String, Map<String, dynamic>> {
// var result = await read(id, params);
try {
var result = await (collection.findAndModify(
query: where.id(_makeId(id)),
remove: true) as FutureOr<Map<String, dynamic>>);
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);

View file

@ -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

View file

@ -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<String, Map<String, dynamic>, 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(<String, dynamic>{});
@ -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 {

View file

@ -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(', ')}]';

View file

@ -189,12 +189,11 @@ class ${pascal}Decoder extends Converter<Map, $pascal> {
// 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<Map, $pascal> {
'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<Map, $pascal> {
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<Map, $pascal> {
// 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<Map, $pascal> {
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<Map, $pascal> {
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<Map, $pascal> {
''';
} 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
)
''';