diff --git a/.gitignore b/.gitignore index 678efe20..07086897 100644 --- a/.gitignore +++ b/.gitignore @@ -40,11 +40,10 @@ pubspec.lock ## VsCode .vscode/ -#.vscode/* -#!.vscode/settings.json -#!.vscode/tasks.json -#!.vscode/launch.json -#!.vscode/extensions.json +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json # IntelliJ .idea/ @@ -75,3 +74,4 @@ logs/ *.pem .DS_Store server_log.txt +ormapp/ \ No newline at end of file diff --git a/TODO.md b/TODO.md index 1544778d..4fac4d47 100644 --- a/TODO.md +++ b/TODO.md @@ -2,15 +2,14 @@ ## Short Term Goal -* Migrate all modules to support NNBD -* Fix issues and failed unit test - * ORM +* Fixing issues + * ORM source code generator * OAuth2 * Proxy * Update examples * Update User Guide -* Update `Angel3` website -* Generate performance metric +* Update website +* Performance testing ## Long Term Goal diff --git a/packages/orm/angel_orm_generator/CHANGELOG.md b/packages/orm/angel_orm_generator/CHANGELOG.md index f2dcc19f..1c7ac683 100644 --- a/packages/orm/angel_orm_generator/CHANGELOG.md +++ b/packages/orm/angel_orm_generator/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## 4.0.1 + +* Added `useNullSafetySyntax: true` to `DartEmitter` +* Updated `*Migration` class generator to produce NNBD code +* Updated `*Query` class generator to produce NNBD code +* Updated `*QueryWhere` class generator to produce NNBD code +* Updated `*QueryValues` class generator to produce NNBD code + ## 4.0.0 * Fixed `BuildContext` cast error diff --git a/packages/orm/angel_orm_generator/README.md b/packages/orm/angel_orm_generator/README.md index d6e4f686..a0ca4400 100644 --- a/packages/orm/angel_orm_generator/README.md +++ b/packages/orm/angel_orm_generator/README.md @@ -1,6 +1,6 @@ # Angel3 ORM Generator -[![version](https://img.shields.io/badge/pub-v4.0.0-brightgreen)](https://pub.dartlang.org/packages/angel3_orm_generator) +[![version](https://img.shields.io/badge/pub-v4.0.1-brightgreen)](https://pub.dartlang.org/packages/angel3_orm_generator) [![Null Safety](https://img.shields.io/badge/null-safety-brightgreen)](https://dart.dev/null-safety) [![Gitter](https://img.shields.io/gitter/room/angel_dart/discussion)](https://gitter.im/angel_dart/discussion) diff --git a/packages/orm/angel_orm_generator/lib/src/migration_generator.dart b/packages/orm/angel_orm_generator/lib/src/migration_generator.dart index 3d654cc8..692876a4 100644 --- a/packages/orm/angel_orm_generator/lib/src/migration_generator.dart +++ b/packages/orm/angel_orm_generator/lib/src/migration_generator.dart @@ -45,17 +45,25 @@ class MigrationGenerator extends GeneratorForAnnotation { var resolver = buildStep.resolver; var ctx = await buildOrmContext({}, element, annotation, buildStep, resolver, autoSnakeCaseNames != false); + + if (ctx == null) { + throw 'Invalid ORM build context'; + } + + // Create `FooMigration` class var lib = generateMigrationLibrary(ctx, element, resolver, buildStep); + //if (lib == null) return null; - return DartFormatter().format(lib.accept(DartEmitter()).toString()); + return DartFormatter() + .format(lib.accept(DartEmitter(useNullSafetySyntax: true)).toString()); } - Library generateMigrationLibrary(OrmBuildContext? ctx, ClassElement element, + Library generateMigrationLibrary(OrmBuildContext ctx, ClassElement element, Resolver resolver, BuildStep buildStep) { return Library((lib) { lib.body.add(Class((clazz) { clazz - ..name = '${ctx!.buildContext.modelClassName}Migration' + ..name = '${ctx.buildContext.modelClassName}Migration' ..extend = refer('Migration') ..methods .addAll([buildUpMigration(ctx, lib), buildDownMigration(ctx)]); @@ -63,12 +71,13 @@ class MigrationGenerator extends GeneratorForAnnotation { }); } - Method buildUpMigration(OrmBuildContext? ctx, LibraryBuilder lib) { + Method buildUpMigration(OrmBuildContext ctx, LibraryBuilder lib) { return Method((meth) { var autoIdAndDateFields = const TypeChecker.fromRuntime(Model) - .isAssignableFromType(ctx!.buildContext.clazz.thisType); + .isAssignableFromType(ctx.buildContext.clazz.thisType); meth ..name = 'up' + ..returns = refer('void') ..annotations.add(refer('override')) ..requiredParameters.add(_schemaParam); @@ -125,9 +134,7 @@ class MigrationGenerator extends GeneratorForAnnotation { switch (col.type) { case ColumnType.varChar: methodName = 'varChar'; - if (col.length != null) { - named['length'] = literal(col.length); - } + named['length'] = literal(col.length); break; case ColumnType.serial: methodName = 'serial'; @@ -179,6 +186,7 @@ class MigrationGenerator extends GeneratorForAnnotation { } var field = table.property(methodName).call(positional, named); + var cascade = []; var defaultValue = ctx.buildContext.defaults[name]; @@ -226,12 +234,23 @@ class MigrationGenerator extends GeneratorForAnnotation { } if (cascade.isNotEmpty) { - var b = StringBuffer()..writeln(field.accept(DartEmitter())); + var b = StringBuffer() + ..writeln( + field.accept(DartEmitter(useNullSafetySyntax: true))); - for (var ex in cascade) { + if (cascade.length == 1) { + var ex = cascade[0]; b - ..write('..') - ..writeln(ex.accept(DartEmitter())); + ..write('.') + ..writeln( + ex.accept(DartEmitter(useNullSafetySyntax: true))); + } else { + for (var ex in cascade) { + b + ..write('..') + ..writeln( + ex.accept(DartEmitter(useNullSafetySyntax: true))); + } } field = CodeExpression(Code(b.toString())); @@ -290,6 +309,7 @@ class MigrationGenerator extends GeneratorForAnnotation { return Method((b) { b ..name = 'down' + ..returns = refer('void') ..annotations.add(refer('override')) ..requiredParameters.add(_schemaParam) ..body = Block((b) { diff --git a/packages/orm/angel_orm_generator/lib/src/orm_generator.dart b/packages/orm/angel_orm_generator/lib/src/orm_generator.dart index f15e71c0..3d26a882 100644 --- a/packages/orm/angel_orm_generator/lib/src/orm_generator.dart +++ b/packages/orm/angel_orm_generator/lib/src/orm_generator.dart @@ -41,27 +41,39 @@ class OrmGenerator extends GeneratorForAnnotation { if (element is ClassElement) { var ctx = await buildOrmContext({}, element, annotation, buildStep, buildStep.resolver, autoSnakeCaseNames); + if (ctx == null) { + throw 'Invalid ORM build context'; + } var lib = buildOrmLibrary(buildStep.inputId, ctx); - return lib.accept(DartEmitter()).toString(); + + return lib.accept(DartEmitter(useNullSafetySyntax: true)).toString(); } else { throw 'The @Orm() annotation can only be applied to classes.'; } } - Library buildOrmLibrary(AssetId inputId, OrmBuildContext? ctx) { + Library buildOrmLibrary(AssetId inputId, OrmBuildContext ctx) { return Library((lib) { // Create `FooQuery` class - // Create `FooQueryWhere` class lib.body.add(buildQueryClass(ctx)); + + // Create `FooQueryWhere` class lib.body.add(buildWhereClass(ctx)); + + // Create `FooQueryValues` class lib.body.add(buildValuesClass(ctx)); }); } - Class buildQueryClass(OrmBuildContext? ctx) { + Class buildQueryClass(OrmBuildContext ctx) { return Class((clazz) { - var rc = ctx!.buildContext.modelClassNameRecase; + var rc = ctx.buildContext.modelClassNameRecase; + var queryWhereType = refer('${rc.pascalCase}QueryWhere'); + var nullableQueryWhereType = TypeReference((b) => b + ..symbol = '${rc.pascalCase}QueryWhere' + ..isNullable = true); + clazz ..name = '${rc.pascalCase}Query' ..extend = TypeReference((b) { @@ -78,6 +90,10 @@ class OrmGenerator extends GeneratorForAnnotation { b ..name = 'casts' ..annotations.add(refer('override')) + ..returns = TypeReference((b) => b + ..symbol = 'Map' + ..types.add(refer('String')) + ..types.add(refer('String'))) ..type = MethodType.getter ..body = Block((b) { var args = {}; @@ -110,6 +126,7 @@ class OrmGenerator extends GeneratorForAnnotation { clazz.methods.add(Method((m) { m ..name = 'tableName' + ..returns = refer('String') ..annotations.add(refer('override')) ..type = MethodType.getter ..body = Block((b) { @@ -121,6 +138,10 @@ class OrmGenerator extends GeneratorForAnnotation { clazz.methods.add(Method((m) { m ..name = 'fields' + ..returns = TypeReference((b) => b + ..symbol = 'List' + ..types.add(TypeReference( + (b) => b..symbol = 'String'))) //refer('List') ..annotations.add(refer('override')) ..type = MethodType.getter ..body = Block((b) { @@ -136,7 +157,7 @@ class OrmGenerator extends GeneratorForAnnotation { clazz.fields.add(Field((b) { b ..name = '_where' - ..type = queryWhereType; + ..type = nullableQueryWhereType; })); // Add where getter @@ -144,10 +165,11 @@ class OrmGenerator extends GeneratorForAnnotation { b ..name = 'where' ..type = MethodType.getter - ..returns = queryWhereType + ..returns = nullableQueryWhereType ..annotations.add(refer('override')) ..body = Block((b) => b.addExpression(refer('_where').returned)); })); + // newWhereClause() clazz.methods.add(Method((b) { b @@ -158,12 +180,14 @@ class OrmGenerator extends GeneratorForAnnotation { queryWhereType.newInstance([refer('this')]).returned)); })); - // Add deserialize() + // Add parseRow() clazz.methods.add(Method((m) { m ..name = 'parseRow' ..static = true - ..returns = ctx.buildContext.modelClassType + ..returns = TypeReference((b) => b + ..symbol = '${rc.pascalCase}' + ..isNullable = true) //refer('${rc.pascalCase}?') ..requiredParameters.add(Parameter((b) => b ..name = 'row' ..type = refer('List'))) @@ -225,7 +249,7 @@ class OrmGenerator extends GeneratorForAnnotation { .call([skipToList]); if (relation.type == RelationshipType.hasMany) { parsed = literalList([parsed]); - var pp = parsed.accept(DartEmitter()); + var pp = parsed.accept(DartEmitter(useNullSafetySyntax: true)); parsed = CodeExpression( Code('$pp.where((x) => x != null).toList()')); } @@ -233,7 +257,8 @@ class OrmGenerator extends GeneratorForAnnotation { refer('model').property('copyWith').call([], {name: parsed}); var block = Block((b) => b.addExpression(refer('model').assign(expr))); - var blockStr = block.accept(DartEmitter()); + var blockStr = + block.accept(DartEmitter(useNullSafetySyntax: true)); var ifStr = 'if (row.length > $i) { $blockStr }'; b.statements.add(Code(ifStr)); i += relation.foreign!.effectiveFields.length; @@ -243,15 +268,19 @@ class OrmGenerator extends GeneratorForAnnotation { }); })); + // deserialize clazz.methods.add(Method((m) { m ..name = 'deserialize' + ..returns = refer('Optional<${rc.pascalCase}>') ..annotations.add(refer('override')) ..requiredParameters.add(Parameter((b) => b ..name = 'row' ..type = refer('List'))) ..body = Block((b) { - b.addExpression(refer('parseRow').call([refer('row')]).returned); + b.addExpression(refer('Optional.ofNullable').call([ + refer('parseRow').call([refer('row')]) + ]).returned); }); })); @@ -261,17 +290,18 @@ class OrmGenerator extends GeneratorForAnnotation { ..optionalParameters.add(Parameter((b) => b ..named = true ..name = 'parent' - ..type = refer('Query'))) + ..type = refer('Query?'))) ..optionalParameters.add(Parameter((b) => b ..named = true ..name = 'trampoline' - ..type = TypeReference((b) => b - ..symbol = 'Set' - ..types.add(refer('String'))))) + ..type = refer('Set?'))) + //TypeReference((b) => b + //..symbol = 'Set' + //..types.add(refer('String'))))) ..initializers.add(Code('super(parent: parent)')) ..body = Block((b) { b.statements.addAll([ - Code('trampoline ??= Set();'), + Code('trampoline ??= {};'), Code('trampoline.add(tableName);'), ]); @@ -444,7 +474,8 @@ class OrmGenerator extends GeneratorForAnnotation { if (ctx.relations.values.any((r) => r.type == RelationshipType.hasMany)) { for (var methodName in const ['get', 'update', 'delete']) { clazz.methods.add(Method((b) { - var type = ctx.buildContext.modelClassType.accept(DartEmitter()); + var type = ctx.buildContext.modelClassType + .accept(DartEmitter(useNullSafetySyntax: true)); b ..name = methodName ..annotations.add(refer('override')) @@ -460,8 +491,8 @@ class OrmGenerator extends GeneratorForAnnotation { // This is only allowed with lists. var field = ctx.buildContext.fields.firstWhere((f) => f.name == name); - var typeLiteral = - convertTypeReference(field.type).accept(DartEmitter()); + var typeLiteral = convertTypeReference(field.type) + .accept(DartEmitter(useNullSafetySyntax: true)); merge.add(''' $name: $typeLiteral.from(l.$name ?? [])..addAll(model.$name ?? []) '''); @@ -497,9 +528,9 @@ class OrmGenerator extends GeneratorForAnnotation { }); } - Class buildWhereClass(OrmBuildContext? ctx) { + Class buildWhereClass(OrmBuildContext ctx) { return Class((clazz) { - var rc = ctx!.buildContext.modelClassNameRecase; + var rc = ctx.buildContext.modelClassNameRecase; clazz ..name = '${rc.pascalCase}QueryWhere' ..extend = refer('QueryWhere'); @@ -508,6 +539,7 @@ class OrmGenerator extends GeneratorForAnnotation { clazz.methods.add(Method((m) { m ..name = 'expressionBuilders' + ..returns = refer('List') ..annotations.add(refer('override')) ..type = MethodType.getter ..body = Block((b) { @@ -601,9 +633,10 @@ class OrmGenerator extends GeneratorForAnnotation { }); } - Class buildValuesClass(OrmBuildContext? ctx) { + Class buildValuesClass(OrmBuildContext ctx) { return Class((clazz) { - var rc = ctx!.buildContext.modelClassNameRecase; + var rc = ctx.buildContext.modelClassNameRecase; + clazz ..name = '${rc.pascalCase}QueryValues' ..extend = refer('MapQueryValues'); @@ -612,6 +645,7 @@ class OrmGenerator extends GeneratorForAnnotation { clazz.methods.add(Method((b) { b ..name = 'casts' + ..returns = refer('Map') ..annotations.add(refer('override')) ..type = MethodType.getter ..body = Block((b) { @@ -725,10 +759,11 @@ class OrmGenerator extends GeneratorForAnnotation { } var cond = prop.notEqualTo(literalNull); - var condStr = cond.accept(DartEmitter()); + var condStr = + cond.accept(DartEmitter(useNullSafetySyntax: true)); var blkStr = Block((b) => b.addExpression(target.assign(parsedId))) - .accept(DartEmitter()); + .accept(DartEmitter(useNullSafetySyntax: true)); var ifStmt = Code('if ($condStr) { $blkStr }'); b.statements.add(ifStmt); } diff --git a/packages/orm/angel_orm_generator/pubspec.yaml b/packages/orm/angel_orm_generator/pubspec.yaml index ebaa6902..fe685101 100644 --- a/packages/orm/angel_orm_generator/pubspec.yaml +++ b/packages/orm/angel_orm_generator/pubspec.yaml @@ -1,5 +1,5 @@ name: angel3_orm_generator -version: 4.0.0 +version: 4.0.1 description: Code generators for Angel3 ORM. Generates query builder classes. homepage: https://angel3-framework.web.app/ repository: https://github.com/dukefirehawk/angel/tree/angel3/packages/orm/angel_orm_generator @@ -26,7 +26,6 @@ dependencies: dev_dependencies: angel3_framework: ^4.0.0 angel3_migration: ^4.0.0 - #angel_test: ^1.0.0 build_runner: ^2.0.1 pedantic: ^1.11.0 postgres: ^2.3.2