diff --git a/.idea/runConfigurations/Controller.xml b/.idea/runConfigurations/Controller.xml new file mode 100644 index 00000000..38315109 --- /dev/null +++ b/.idea/runConfigurations/Controller.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Update.xml b/.idea/runConfigurations/Update.xml new file mode 100644 index 00000000..75cab2d3 --- /dev/null +++ b/.idea/runConfigurations/Update.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/bin/angel.dart b/bin/angel.dart index 6a8ae5ee..ee16c084 100644 --- a/bin/angel.dart +++ b/bin/angel.dart @@ -1,12 +1,9 @@ #!/usr/bin/env dart -library demon.tool; +library angel_cli.tool; import "dart:io"; import "package:args/command_runner.dart"; import 'package:angel_cli/angel_cli.dart'; -import 'package:angel_cli/pubspec.dart'; -import 'package:console/console.dart'; -import 'package:http/http.dart' as http; final String DOCTOR = "doctor"; @@ -15,6 +12,7 @@ main(List args) async { new CommandRunner("angel", "Command-line tools for the Angel framework."); runner + ..addCommand(new ControllerCommand()) ..addCommand(new DoctorCommand()) ..addCommand(new KeyCommand()) ..addCommand(new ServiceCommand()) @@ -22,29 +20,8 @@ main(List args) async { ..addCommand(new TestCommand()) ..addCommand(new PluginCommand()) ..addCommand(new StartCommand()) - ..addCommand(new RenameCommand()); - - stdout.write('Checking for update... '); - - try { - var client = new http.Client(); - var update = await checkForUpdate(client); - client.close(); - - if (update != null) { - stdout.writeln(); - var pen = new TextPen(); - pen.cyan(); - pen.text( - 'ATTENTION: There is a new version of the Angel CLI available (version $update).'); - pen.text('\nTo update, run `pub global activate angel_cli`.'); - pen(); - stdout.writeln(); - } else - stdout.writeln('No update available.'); - } catch (e) { - stdout.writeln('Failed to check for update.'); - } + ..addCommand(new RenameCommand()) + ..addCommand(new UpdateCommand()); return await runner.run(args).then((_) {}).catchError((exc) { stderr.writeln("Oops, something went wrong: $exc"); diff --git a/lib/angel_cli.dart b/lib/angel_cli.dart index 3a879ac2..4d3fa997 100644 --- a/lib/angel_cli.dart +++ b/lib/angel_cli.dart @@ -1,3 +1,3 @@ -library demon; +library angel_cli; export 'src/commands/commands.dart'; \ No newline at end of file diff --git a/lib/pubspec.dart b/lib/pubspec.dart deleted file mode 100644 index 874a4c7a..00000000 --- a/lib/pubspec.dart +++ /dev/null @@ -1 +0,0 @@ -export 'src/pubspec.update.g.dart'; \ No newline at end of file diff --git a/lib/src/commands/commands.dart b/lib/src/commands/commands.dart index bccb48f1..43ab86ed 100644 --- a/lib/src/commands/commands.dart +++ b/lib/src/commands/commands.dart @@ -1,5 +1,6 @@ library angel_cli.commands; +export 'controller.dart'; export "doctor.dart"; export "key.dart"; export "init.dart"; @@ -7,4 +8,5 @@ export "plugin.dart"; export "rename.dart"; export "service.dart"; export "start.dart"; -export "test.dart"; \ No newline at end of file +export "test.dart"; +export 'update.dart'; \ No newline at end of file diff --git a/lib/src/commands/controller.dart b/lib/src/commands/controller.dart new file mode 100644 index 00000000..fbf5a06d --- /dev/null +++ b/lib/src/commands/controller.dart @@ -0,0 +1,66 @@ +import 'dart:io'; +import 'package:args/command_runner.dart'; +import 'package:code_builder/code_builder.dart'; +import "package:console/console.dart"; +import 'package:pubspec/pubspec.dart'; +import 'package:recase/recase.dart'; + +class ControllerCommand extends Command { + final TextPen _pen = new TextPen(); + + @override + String get name => "controller"; + + @override + String get description => + "Creates a new controller within the given project."; + + @override + run() async { + final name = await readInput("Name of Controller: "), + recase = new ReCase(name), + lower = recase.snakeCase; + final controllersDir = new Directory("lib/src/routes/controllers"); + final controllerFile = + new File.fromUri(controllersDir.uri.resolve("$lower.dart")); + + if (!await controllerFile.exists()) + await controllerFile.create(recursive: true); + + await controllerFile.writeAsString( + _generateController(await PubSpec.load(Directory.current), recase)); + + _pen.green(); + _pen("${Icon.CHECKMARK} Successfully generated controller $name."); + _pen(); + } + + NewInstanceBuilder _expose(String path) => new TypeBuilder('Expose') + .constInstance([], namedArguments: {'path': literal(path)}); + + String _generateController(PubSpec pubspec, ReCase recase) { + var lower = recase.snakeCase; + var lib = new LibraryBuilder('${pubspec.name}.routes.controllers.$lower'); + lib.addDirective( + new ImportBuilder('package:angel_common/angel_common.dart')); + + var clazz = new ClassBuilder('${recase.pascalCase}Controller', + asExtends: new TypeBuilder('Controller')); + + // Add @Expose() + clazz.addAnnotation(_expose('/$lower')); + + // Add + // @Expose(path: '/') + // String foo() => 'bar'; + + var meth = new MethodBuilder('foo', + returns: literal('bar'), returnType: new TypeBuilder('String')); + meth.addAnnotation(_expose('/')); + clazz.addMethod(meth); + + lib.addMember(clazz); + + return prettyToSource(lib.buildAst()); + } +} diff --git a/lib/src/commands/init.dart b/lib/src/commands/init.dart index 7b01a35e..69917acb 100644 --- a/lib/src/commands/init.dart +++ b/lib/src/commands/init.dart @@ -64,7 +64,14 @@ class InitCommand extends Command { ..text('`angel start`') ..normal() ..text(' in your terminal.') - ..text('\nHappy coding!') + ..text('\n\nFind more documentation about Angel:') + ..text('\n * https://angel-dart.github.io') + ..text('\n * https://github.com/angel-dart/angel/wiki') + ..text( + '\n * https://www.youtube.com/playlist?list=PLl3P3tmiT-frEV50VdH_cIrA2YqIyHkkY') + ..text('\n * https://medium.com/the-angel-framework') + ..text('\n * https://dart.academy/tag/angel') + ..text('\n\nHappy coding!') ..call(); } @@ -145,7 +152,8 @@ class InitCommand extends Command { static String resolvePub() { var exec = new File(Platform.resolvedExecutable); var pubPath = exec.parent.uri.resolve('pub').path; - if (Platform.isWindows) pubPath = pubPath.replaceAll(_leadingSlashes, '') + '.bat'; + if (Platform.isWindows) + pubPath = pubPath.replaceAll(_leadingSlashes, '') + '.bat'; pubPath = Uri.decodeFull(pubPath); return pubPath; } diff --git a/lib/src/pubspec.update.g.dart b/lib/src/commands/pubspec.update.g.dart similarity index 94% rename from lib/src/pubspec.update.g.dart rename to lib/src/commands/pubspec.update.g.dart index 507249b4..9d141f37 100644 --- a/lib/src/pubspec.update.g.dart +++ b/lib/src/commands/pubspec.update.g.dart @@ -3,7 +3,7 @@ import 'dart:convert'; import 'package:http/src/base_client.dart' as http; import 'package:pub_semver/pub_semver.dart'; -final Version PACKAGE_VERSION = new Version(1, 1, 0); +final Version PACKAGE_VERSION = new Version(1, 1, 1); Future fetchCurrentVersion(http.BaseClient client) async { var response = await client.get('https://pub.dartlang.org/api/packages/angel_cli'); diff --git a/lib/src/commands/service.dart b/lib/src/commands/service.dart index c5c682f7..0e7a00f1 100644 --- a/lib/src/commands/service.dart +++ b/lib/src/commands/service.dart @@ -10,6 +10,7 @@ import 'init.dart' show preBuild; const List GENERATORS = const [ const MapServiceGenerator(), + const FileServiceGenerator(), const MongoServiceGenerator(), const RethinkServiceGenerator(), const CustomServiceGenerator() @@ -70,7 +71,7 @@ class ServiceCommand extends Command { await runConfig.writeAsString(_generateRunConfiguration(name, lower)); } - if (generator.createsModel == true) { + if (generator.createsModel == true || typed == true) { await _generateModel(pubspec, name, lower); } @@ -78,7 +79,7 @@ class ServiceCommand extends Command { await _generateValidator(pubspec, lower, rc.constantCase); } - if (generator.exportedInServiceLibrary == true) { + if (generator.exportedInServiceLibrary == true || typed == true) { var serviceLibrary = new File('lib/src/models/models.dart'); await serviceLibrary.writeAsString("\nexport '$lower.dart';", mode: FileMode.APPEND); diff --git a/lib/src/commands/service_generators/file_service.dart b/lib/src/commands/service_generators/file_service.dart new file mode 100644 index 00000000..7778e2d9 --- /dev/null +++ b/lib/src/commands/service_generators/file_service.dart @@ -0,0 +1,26 @@ +import 'generator.dart'; +import 'package:code_builder/code_builder.dart'; +import 'package:inflection/inflection.dart'; + +class FileServiceGenerator extends ServiceGenerator { + const FileServiceGenerator() : super('Persistent JSON File'); + + @override + bool get createsModel => false; + + @override + void applyToLibrary(LibraryBuilder library, String name, String lower) { + library.addMember(new ImportBuilder('dart:io')); + library.addMember(new ImportBuilder( + 'package:angel_file_service/angel_file_service.dart')); + } + + @override + ExpressionBuilder createInstance( + MethodBuilder methodBuilder, String name, String lower) { + return new TypeBuilder('JsonFileService').newInstance([ + new TypeBuilder('File') + .newInstance([literal(pluralize(lower) + '_db.json')]) + ]); + } +} diff --git a/lib/src/commands/service_generators/service_generators.dart b/lib/src/commands/service_generators/service_generators.dart index 760cd927..658cc16b 100644 --- a/lib/src/commands/service_generators/service_generators.dart +++ b/lib/src/commands/service_generators/service_generators.dart @@ -1,4 +1,5 @@ export 'custom.dart'; +export 'file_service.dart'; export 'generator.dart'; export 'map.dart'; export 'mongo.dart'; diff --git a/lib/src/commands/test.dart b/lib/src/commands/test.dart index 47c022e0..fdb5dee7 100644 --- a/lib/src/commands/test.dart +++ b/lib/src/commands/test.dart @@ -61,18 +61,14 @@ import 'package:angel_test/angel_test.dart'; import 'package:test/test.dart'; main() async { - Angel app; TestClient client; setUp(() async { - app = await createServer(); + var app = await createServer(); client = await connectTo(app); }); - tearDown(() async { - await client.close(); - app = null; - }); + tearDown(() => client.close()); test('$lower', () async { final response = await client.get('/$lower'); diff --git a/lib/src/commands/update.dart b/lib/src/commands/update.dart new file mode 100644 index 00000000..8f17b579 --- /dev/null +++ b/lib/src/commands/update.dart @@ -0,0 +1,66 @@ +import 'dart:io'; +import 'package:args/command_runner.dart'; +import 'package:console/console.dart'; +import 'package:http/http.dart' as http; +import 'init.dart'; +import 'pubspec.update.g.dart'; + +class UpdateCommand extends Command { + @override + String get name => 'update'; + + @override + String get description => 'Updates the Angel CLI, if an update is available.'; + + @override + run() async { + stdout.write('Checking for update... '); + + try { + var client = new http.Client(); + var update = await checkForUpdate(client); + client.close(); + + if (update != null) { + stdout.writeln(); + var pen = new TextPen(); + pen.cyan(); + pen.text( + 'ATTENTION: There is a new version of the Angel CLI available (version $update).'); + pen.call(); + var prompt = new Chooser(['Yes', 'No']); + print('Update now?'); + var choice = await prompt.choose(); + + if (choice != 'Yes') { + pen.reset(); + pen.cyan(); + pen.text( + 'When you are ready to update, run `pub global activate angel_cli`.'); + pen(); + stdout.writeln(); + } else { + var pubPath = InitCommand.resolvePub(); + print('Running `pub global activate` using $pubPath...'); + var p = + await Process.start(pubPath, ['global', 'activate', 'angel_cli']); + p.stderr.listen(stderr.add); + p.stdout.listen(stdout.add); + var exitCode = await p.exitCode; + + if (exitCode != 0) + throw 'Pub terminated with a non-zero exit code.'; + else { + pen.reset(); + pen.green(); + pen("${Icon.CHECKMARK} Successfully updated the Angel CLI to version $update.\n"); + pen(); + } + } + } else + stdout.writeln('No update available.'); + } catch (e) { + stdout.writeln('Failed to check for update.'); + } + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 0fac6821..0f44f331 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,11 +2,11 @@ author: "Tobe O " description: "Command-line tools for the Angel framework." homepage: "https://github.com/angel-dart/angel_cli" name: "angel_cli" -version: 1.1.0 +version: 1.1.1 dependencies: # analyzer: "^0.29.0" - args: "^0.13.7" - code_builder: "^1.0.0-beta" + args: ^0.13.4 + code_builder: ^1.0.0 console: "^2.2.3" glob: "^1.1.0" http: ^0.11.3 diff --git a/tool/phases.dart b/tool/phases.dart index 9e82fe33..94bcdbf6 100644 --- a/tool/phases.dart +++ b/tool/phases.dart @@ -2,5 +2,5 @@ import 'package:build_runner/build_runner.dart'; import 'package:check_for_update/builder.dart'; final PhaseGroup phaseGroup = new PhaseGroup.singleAction( - new CheckForUpdateBuilder(subDirectory: 'lib/src'), + new CheckForUpdateBuilder(subDirectory: 'lib/src/commands'), new InputSet('angel_cli', const ['pubspec.yaml']));