import 'dart:io'; import 'package:args/command_runner.dart'; import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; import 'package:inflection/inflection.dart'; import 'package:io/ansi.dart'; import 'package:prompts/prompts.dart' as prompts; import 'package:recase/recase.dart'; import '../../util.dart'; import 'maker.dart'; class ModelCommand extends Command { @override String get name => 'model'; @override String get description => 'Generates a model class.'; ModelCommand() { argParser ..addFlag('migration', abbr: 'm', help: 'Generate an angel_orm migration file.', negatable: false) ..addFlag('orm', help: 'Generate angel_orm code.', negatable: false) ..addFlag('serializable', help: 'Generate angel_serialize annotations.', defaultsTo: true) ..addOption('name', abbr: 'n', help: 'Specifies a name for the model class.') ..addOption('output-dir', help: 'Specifies a directory to create the model class in.', defaultsTo: 'lib/src/models') ..addOption('migration-dir', help: 'Specifies a directory to create the migration class in.', defaultsTo: 'tool/migrations'); } @override run() async { var pubspec = await loadPubspec(); String name; if (argResults.wasParsed('name')) name = argResults['name'] as String; if (name?.isNotEmpty != true) { name = prompts.get('Name of model class'); } List<MakerDependency> deps = [ const MakerDependency('angel_framework', '^1.0.0'), const MakerDependency('angel_model', '^1.0.0'), ]; var rc = new ReCase(name); var modelLib = new Library((modelLib) { modelLib.directives .add(new Directive.import('package:angel_model/angel_model.dart')); var needsSerialize = argResults['serializable'] as bool || argResults['orm'] as bool; if (needsSerialize) { modelLib.directives.add(new Directive.import( 'package:angel_serialize/angel_serialize.dart')); deps.add(const MakerDependency('angel_serialize', '^2.0.0')); } if (argResults['orm'] as bool) { modelLib.directives .add(new Directive.import('package:angel_orm/angel_orm.dart')); deps.add(const MakerDependency('angel_orm', '^1.0.0-alpha')); } modelLib.body.add(new Class((modelClazz) { modelClazz ..name = needsSerialize ? '_${rc.pascalCase}' : rc.pascalCase ..extend = refer('Model'); if (needsSerialize) { // TODO: Add parts // modelLib.addDirective(new PartBuilder('${rc.snakeCase}.g.dart')); modelClazz.annotations.add(refer('serializable')); } if (argResults['orm'] as bool) { modelClazz.annotations.add(refer('orm')); } })); }); // Save model file var outputDir = new Directory.fromUri( Directory.current.uri.resolve(argResults['output-dir'] as String)); var modelFile = new File.fromUri(outputDir.uri.resolve('${rc.snakeCase}.dart')); if (!await modelFile.exists()) await modelFile.create(recursive: true); await modelFile.writeAsString(new DartFormatter() .format(modelLib.accept(new DartEmitter()).toString())); print(green .wrap('$checkmark Created model file "${modelFile.absolute.path}".')); if (argResults['migration'] as bool) { deps.add(const MakerDependency('angel_migration', '^1.0.0-alpha')); var migrationLib = new Library((migrationLib) { migrationLib ..directives.add(new Directive.import( 'package:angel_migration.dart/angel_migration.dart')) ..body.add(new Class((migrationClazz) { migrationClazz ..name = '${rc.pascalCase}Migration' ..extend = refer('Migration'); var tableName = pluralize(rc.snakeCase); // up() migrationClazz.methods.add(new Method((up) { up ..name = 'up' ..returns = refer('void') ..annotations.add(refer('override')) ..requiredParameters.add(new Parameter((b) => b ..name = 'schema' ..type = refer('Schema'))) ..body = new Block((block) { // (table) { ... } var callback = new Method((callback) { callback ..requiredParameters .add(new Parameter((b) => b..name = 'table')) ..body = new Block((block) { var table = refer('table'); block.addExpression( (table.property('serial').call([literal('id')])) .property('primaryKey') .call([]), ); block.addExpression( table.property('date').call([ literal('created_at'), ]), ); block.addExpression( table.property('date').call([ literal('updated_at'), ]), ); }); }); block.addExpression(refer('schema').property('create').call([ literal(tableName), callback.closure, ])); }); })); // down() migrationClazz.methods.add(new Method((down) { down ..name = 'down' ..returns = refer('void') ..annotations.add(refer('override')) ..requiredParameters.add(new Parameter((b) => b ..name = 'schema' ..type = refer('Schema'))) ..body = new Block((block) { block.addExpression( refer('schema').property('drop').call([ literal(tableName), ]), ); }); })); })); }); // Save migration file var migrationDir = new Directory.fromUri( Directory.current.uri.resolve(argResults['migration-dir'] as String)); var migrationFile = new File.fromUri(migrationDir.uri.resolve('${rc.snakeCase}.dart')); if (!await migrationFile.exists()) await migrationFile.create(recursive: true); await migrationFile.writeAsString(new DartFormatter() .format(migrationLib.accept(new DartEmitter()).toString())); print(green.wrap( '$checkmark Created migration file "${migrationFile.absolute.path}".')); } if (deps.isNotEmpty) await depend(deps); } }