This commit is contained in:
thosakwe 2017-03-24 16:25:50 -04:00
parent f849ce9a83
commit afca3b0752
11 changed files with 154 additions and 31 deletions

View file

@ -4,10 +4,13 @@ library demon.tool;
import "dart:io"; import "dart:io";
import "package:args/command_runner.dart"; import "package:args/command_runner.dart";
import 'package:angel_cli/angel_cli.dart'; import 'package:angel_cli/angel_cli.dart';
import 'package:angel_cli/pubspec.update.g.dart';
import 'package:console/console.dart';
import 'package:http/http.dart' as http;
final String DOCTOR = "doctor"; final String DOCTOR = "doctor";
main(List<String> args) { main(List<String> args) async {
var runner = var runner =
new CommandRunner("angel", "Command-line tools for the Angel framework."); new CommandRunner("angel", "Command-line tools for the Angel framework.");
@ -21,7 +24,24 @@ main(List<String> args) {
..addCommand(new StartCommand()) ..addCommand(new StartCommand())
..addCommand(new RenameCommand()); ..addCommand(new RenameCommand());
return runner.run(args).then((_) {}).catchError((exc) { stdout.write('Checking for update... ');
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.');
return await runner.run(args).then((_) {}).catchError((exc) {
stderr.writeln("Oops, something went wrong: $exc"); stderr.writeln("Oops, something went wrong: $exc");
exitCode = 1; exitCode = 1;
}); });

26
lib/pubspec.update.g.dart Normal file
View file

@ -0,0 +1,26 @@
import 'dart:async';
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, 0, 6);
Future<Version> fetchCurrentVersion(http.BaseClient client) async {
var response =
await client.get('https://pub.dartlang.org/api/packages/angel_cli');
var json = JSON.decode(response.body) as Map;
if (!(json.containsKey('latest')) ||
!(json['latest'].containsKey('pubspec')) ||
!(json['latest']['pubspec'].containsKey('version'))) {
throw new StateError(
'GET https://pub.dartlang.org/api/packages/angel_cli returned an invalid pub API response.');
}
return new Version.parse(json['latest']['pubspec']['version']);
}
Future<Version> checkForUpdate(http.BaseClient client) async {
var current = await fetchCurrentVersion(client);
if (PACKAGE_VERSION.compareTo(current) < 0) {
return current;
}
return null;
}

View file

@ -17,7 +17,9 @@ class InitCommand extends Command {
String get description => String get description =>
"Initializes a new Angel project in the current directory."; "Initializes a new Angel project in the current directory.";
InitCommand() {} InitCommand() {
argParser.addFlag('pub-get', defaultsTo: true);
}
@override @override
run() async { run() async {
@ -38,15 +40,60 @@ class InitCommand extends Command {
new File.fromUri(projectDir.uri.resolve('config/production.yaml')), new File.fromUri(projectDir.uri.resolve('config/production.yaml')),
secret); secret);
var name = p.basenameWithoutExtension(projectDir.path); var name = p.basenameWithoutExtension(
projectDir.absolute.uri.normalizePath().toFilePath());
print('Renaming project from "angel" to "$name"...'); print('Renaming project from "angel" to "$name"...');
await renamePubspec(projectDir, 'angel', name); await renamePubspec(projectDir, 'angel', name);
await renameDartFiles(projectDir, 'angel', name); await renameDartFiles(projectDir, 'angel', name);
if (argResults['pub-get'] != false) {
print('Now running pub get...');
await _pubGet(projectDir);
}
_pen.green(); _pen.green();
_pen( _pen("${Icon.CHECKMARK} Successfully initialized Angel project.");
"${Icon.CHECKMARK} Successfully initialized Angel project. Now running pub get...");
_pen(); _pen();
await _pubGet(projectDir); _pen
..reset()
..text('\nCongratulations! You are ready to start developing with Angel!')
..text('\nTo start the server (with file watching), run ')
..magenta()
..text('`angel start`')
..normal()
..text(' in your terminal.')
..text('\nHappy coding!')
..call();
}
_deleteRecursive(FileSystemEntity entity, [bool self = true]) async {
if (entity is Directory) {
await for (var entity in entity.list(recursive: true)) {
try {
await _deleteRecursive(entity);
} catch (e) {}
}
try {
if (self != false) await entity.delete(recursive: true);
} catch (e) {}
} else if (entity is File) {
try {
await entity.delete(recursive: true);
} catch (e) {}
} else if (entity is Link) {
var path = await entity.resolveSymbolicLinks();
var stat = await FileStat.stat(path);
switch (stat.type) {
case FileSystemEntityType.DIRECTORY:
return await _deleteRecursive(new Directory(path));
case FileSystemEntityType.FILE:
return await _deleteRecursive(new File(path));
default:
break;
}
}
} }
_cloneRepo(Directory projectDir) async { _cloneRepo(Directory projectDir) async {
@ -54,11 +101,16 @@ class InitCommand extends Command {
if (await projectDir.exists()) { if (await projectDir.exists()) {
var chooser = new Chooser(["Yes", "No"], var chooser = new Chooser(["Yes", "No"],
message: message:
"Directory '${projectDir.absolute.path}' exists. Overwrite it? (Yes/No)"); "Directory '${projectDir.absolute.path}' already exists. Overwrite it? (Yes/No)");
if (await chooser.choose() != "Yes") if (await chooser.choose() != "Yes")
throw new Exception("Chose not to overwrite existing directory."); throw new Exception("Chose not to overwrite existing directory.");
await projectDir.delete(recursive: true); else if (projectDir.absolute.uri.normalizePath().toFilePath() !=
Directory.current.absolute.uri.normalizePath().toFilePath())
await projectDir.delete(recursive: true);
else {
await _deleteRecursive(projectDir, false);
}
} }
var git = await Process.start("git", [ var git = await Process.start("git", [
@ -89,7 +141,10 @@ class InitCommand extends Command {
} }
_pubGet(Directory projectDir) async { _pubGet(Directory projectDir) async {
var pub = await Process.start("pub", ["get"], var exec = new File(Platform.resolvedExecutable);
var pubPath = exec.parent.uri.resolve('pub').path;
print('Running pub at "$pubPath"...');
var pub = await Process.start(pubPath, ["get"],
workingDirectory: projectDir.absolute.path); workingDirectory: projectDir.absolute.path);
stdout.addStream(pub.stdout); stdout.addStream(pub.stdout);
stderr.addStream(pub.stderr); stderr.addStream(pub.stderr);

View file

@ -1,6 +1,8 @@
import 'dart:io'; import 'dart:io';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import "package:console/console.dart"; import "package:console/console.dart";
import 'package:pubspec/pubspec.dart';
import 'package:recase/recase.dart';
class PluginCommand extends Command { class PluginCommand extends Command {
final TextPen _pen = new TextPen(); final TextPen _pen = new TextPen();
@ -13,24 +15,24 @@ class PluginCommand extends Command {
@override @override
run() async { run() async {
final name = await readInput("Name of Plugin: "), lower = name.toLowerCase(); var pubspec = await PubSpec.load(Directory.current);
final name = await readInput("Name of Plugin: "),
lower = new ReCase(name).snakeCase;
final testDir = new Directory("lib/src/config/plugins"); final testDir = new Directory("lib/src/config/plugins");
final pluginFile = new File.fromUri( final pluginFile = new File.fromUri(testDir.uri.resolve("$lower.dart"));
testDir.uri.resolve("$lower.dart"));
if (!await pluginFile.exists()) if (!await pluginFile.exists()) await pluginFile.create(recursive: true);
await pluginFile.create(recursive: true);
await pluginFile.writeAsString(_generatePlugin(lower)); await pluginFile.writeAsString(_generatePlugin(pubspec, name, lower));
_pen.green(); _pen.green();
_pen("${Icon.CHECKMARK} Successfully generated plugin $name."); _pen("${Icon.CHECKMARK} Successfully generated plugin $name.");
_pen(); _pen();
} }
String _generatePlugin(String name) { String _generatePlugin(PubSpec pubspec, String name, String lower) {
return ''' return '''
library ${pubspec.name}.plugins.$lower;
import 'dart:async'; import 'dart:async';
import 'package:angel_framework/angel_framework.dart'; import 'package:angel_framework/angel_framework.dart';

View file

@ -71,11 +71,11 @@ class ServiceCommand extends Command {
} }
if (generator.createsModel == true) { if (generator.createsModel == true) {
await _generateModel(name, lower); await _generateModel(pubspec, name, lower);
} }
if (generator.createsValidator == true) { if (generator.createsValidator == true) {
await _generateValidator(lower, rc.constantCase); await _generateValidator(pubspec, lower, rc.constantCase);
} }
if (generator.exportedInServiceLibrary == true) { if (generator.exportedInServiceLibrary == true) {
@ -152,34 +152,33 @@ class ServiceCommand extends Command {
return prettyToSource(lib.buildAst()); return prettyToSource(lib.buildAst());
} }
_generateModel(String name, String lower) async { _generateModel(PubSpec pubspec, String name, String lower) async {
var file = new File('lib/src/models/$lower.dart'); var file = new File('lib/src/models/$lower.dart');
if (!await file.exists()) await file.createSync(recursive: true); if (!await file.exists()) await file.createSync(recursive: true);
await file.writeAsString(''' await file.writeAsString('''
library ${pubspec.name}.models.$lower;
import 'package:angel_framework/common.dart'; import 'package:angel_framework/common.dart';
class $name extends Model { class $name extends Model {
String name; @override
String id;
String desc; String name, desc;
$name({String id, this.name, this.desc}) { $name({this.id, this.name, this.desc});
this.id = id;
}
} }
''' '''
.trim()); .trim());
} }
_generateValidator(String lower, String constantCase) async { _generateValidator(PubSpec pubspec, String lower, String constantCase) async {
var file = new File('lib/src/validators/$lower.dart'); var file = new File('lib/src/validators/$lower.dart');
if (!await file.exists()) await file.createSync(recursive: true); if (!await file.exists()) await file.createSync(recursive: true);
await file.writeAsString(''' await file.writeAsString('''
library ${pubspec.name}.models.$lower;
import 'package:angel_validate/angel_validate.dart'; import 'package:angel_validate/angel_validate.dart';
final Validator $constantCase = new Validator({ final Validator $constantCase = new Validator({

View file

@ -25,6 +25,7 @@ class RethinkServiceGenerator extends ServiceGenerator {
ExpressionBuilder createInstance( ExpressionBuilder createInstance(
MethodBuilder methodBuilder, String name, String lower) { MethodBuilder methodBuilder, String name, String lower) {
return new TypeBuilder('RethinkService').newInstance([ return new TypeBuilder('RethinkService').newInstance([
reference('connection'),
reference('r').invoke('table', [literal(pluralize(lower))]) reference('r').invoke('table', [literal(pluralize(lower))])
]); ]);
} }

View file

@ -2,6 +2,7 @@ import 'dart:io';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import "package:console/console.dart"; import "package:console/console.dart";
import 'package:pubspec/pubspec.dart'; import 'package:pubspec/pubspec.dart';
import 'package:recase/recase.dart';
class TestCommand extends Command { class TestCommand extends Command {
final TextPen _pen = new TextPen(); final TextPen _pen = new TextPen();
@ -14,7 +15,8 @@ class TestCommand extends Command {
@override @override
run() async { run() async {
final name = await readInput("Name of Test: "), lower = name.toLowerCase(); final name = await readInput("Name of Test: "),
lower = new ReCase(name).snakeCase;
final testDir = new Directory("test/services"); final testDir = new Directory("test/services");
final testFile = final testFile =
new File.fromUri(testDir.uri.resolve("${lower}_test.dart")); new File.fromUri(testDir.uri.resolve("${lower}_test.dart"));

View file

@ -2,13 +2,14 @@ author: "Tobe O <thosakwe@gmail.com>"
description: "Command-line tools for the Angel framework." description: "Command-line tools for the Angel framework."
homepage: "https://github.com/angel-dart/angel_cli" homepage: "https://github.com/angel-dart/angel_cli"
name: "angel_cli" name: "angel_cli"
version: "1.0.6" version: "1.0.7"
dependencies: dependencies:
# analyzer: "^0.29.0" # analyzer: "^0.29.0"
args: "^0.13.7" args: "^0.13.7"
code_builder: "^1.0.0-beta" code_builder: "^1.0.0-beta"
console: "^2.2.3" console: "^2.2.3"
glob: "^1.1.0" glob: "^1.1.0"
http: ^0.11.3
id: "^1.0.0" id: "^1.0.0"
inflection: "^0.4.1" inflection: "^0.4.1"
pubspec: "^0.0.14" pubspec: "^0.0.14"
@ -16,6 +17,9 @@ dependencies:
recase: "^1.0.0" recase: "^1.0.0"
watcher: "^0.9.7" watcher: "^0.9.7"
yaml: "^2.0.0" yaml: "^2.0.0"
dev_dependencies:
build_runner: ^0.3.0
check_for_update: ^1.0.0
environment: environment:
sdk: ">=1.19.0" sdk: ">=1.19.0"
executables: executables:

4
tool/build.dart Normal file
View file

@ -0,0 +1,4 @@
import 'package:build_runner/build_runner.dart';
import 'phases.dart';
main() => build(phaseGroup, deleteFilesByDefault: true);

6
tool/phases.dart Normal file
View file

@ -0,0 +1,6 @@
import 'package:build_runner/build_runner.dart';
import 'package:check_for_update/builder.dart';
final PhaseGroup phaseGroup = new PhaseGroup.singleAction(
new CheckForUpdateBuilder(subDirectory: 'lib'),
new InputSet('angel_cli', const ['pubspec.yaml']));

4
tool/watch.dart Normal file
View file

@ -0,0 +1,4 @@
import 'package:build_runner/build_runner.dart';
import 'phases.dart';
main() => watch(phaseGroup, deleteFilesByDefault: true);